隐式转换
- 加法的隐式转换
-
+号的两边 一边为字符串 一边为数字
- 先将非字符串转换为字符串 然后再拼接
-
返回值: 字符串
console.log('1'+1+1); //网页输出字符串111 console.log('1'+(1+1)); //输出字符串12, 需要计算加法再接-->加上小括号 function demo() { console.log('1'); setTimeout(function(){ console.log(2); },1000); setTimeout(function(){ console.log(3); },0); console.log('4'); }; demo(); // 1 4 3 2 页面里所有的setTimeout定义的操作,都将放在同一列队中依次执行. 而列队执行的时间需要等到函数调用栈执行完毕才会执行, 相当于可执行代码执行完毕, 才会执行setTimeout操作, 且按照延时长短顺序先后执行.
-
- *乘法 | /除法 | %取模 | -减法隐式转换
- 先将非数值转成数值, 然后再运算
document.write('1'*5); //网页输出数字5
- 先将非数值转成数值, 然后再运算
逻辑与&& 逻辑或|| 逻辑非!
-
&&
: 如果与两边不是布尔值, 先去判断左边是不是为真- 左边为真就返回右边的值 无论什么类型的值都要返回
- 左边为假 就返回左边
-
||
: 两边不是布尔值 就先看左边是否为真- 如果左边为真 就返回左边的值
- 如果左边为假 就返回右边的值
-
!
: 如果逻辑非不是布尔值(判断原则非0即真)-先将表达式转换成布尔值-然后再取反
基本类型和复杂类型
- 基本/简单数据类型(存储在【栈内存】)
- number 数值 | string 字符串 | boolean 布尔 | undefined 未定义 | null 空
- 变量的值永远不会为null, 除非手动设置为null
- 什么时候需要把变量的值赋值为null
- 告诉系统不再使用该变量, 可以回收其占用的内存空间
- 复杂/复合数据类型(指针存栈中,具体数据存储在【堆内存】)
- Object | Array | Date | Number | Boolean | String
- null不是对象, js官方的错误:
console.log(typeof null); //object
- 判断数据类型
- 关键字:
typeof
- 语法:
typeof 数据 | 变量
- 返回值: string
- 关键字:
值类型和引用类型
- 值类型: 简单的数据类型属于值类型
- 引用类型: 复杂的数据类型
- 两者区别: 存储的信息不一样
- 值类型: 存储的是具体的数据
- 引用类型: 存储的是引用地址, 该地址指向内存中的一块内存空间, 在这个内存空间存储着具体的数据
值类型/引用类型的赋值
- 赋值: 把右边存储的信息复制一份给左边
- 值类型的赋值: 把右边存储的信息(具体的数据)复制一份给左边
- 特点: 只是简单的数据复制, 互相是独立的, 修改其中一个不会影响另外一个
- 引用类型的赋值: 把右边存储的信息(指向具体的数据的地址)复制一份给左边
- 特点: 共享同一份数据, 修改其中一个对象的属性的值会影响另一个
值类型/引用类型在函数中的使用
- 值类型作为函数的参数(值传递): 实参和形参互不影响
- 引用类型作为函数的参数(地址传递): 实参和形参共享同一份数据, 修改其中一个对象属性的值会影响另一个对象的值
var obj = {name : 'zs'};
function demo(object) {
object.name = 'ls';
object = {name: 'demoName',des :'des'};
console.log(object.name); // demoName
console.log(object.des); // des
}
demo(obj);
console.log(obj.name); // ls
console.log(obj.des); // undefined (内部的object是函数内部变量,函数执行完毕就销毁了,所以object也没有了)
console.log(obj); // {name: "ls"}
对象的动态特性
- 定义: 对已经定义好的对象, 进行一些操作, 删除/增加属性
- 通过点语法访问对象属性
如果不存在该属性就是增加操作. 如果存在该属性就是修改操作
-
delete
删除对象属性console.log(delete obj.age); // undefined
- 通过[]语法访问对象属性
- 键(属性名)是字符串:
obj['key']
- 键(属性名)是字符串:
in
- for..in: 遍历对象的key
- 判断对象中是否存在指定的属性
- 语法:
"属性名" in 对象
- 在数组中的使用, in操作的是索引
- 怎么判断数组中是否存在指定的元素
arr.indexOf(123); //返回数组中某个元素的索引;如果不存在该元素,返回-1
- 遍历数组-判断是否等于指定元素
- 怎么判断数组中是否存在指定的元素
- 语法:
delete
- 定义: 可以删除对象中属性, 删除后该属性为undefined
- 返回值: 布尔值(表示是否删除成功)
- 特点
-
可以删除未使用var声明的变量, 不可删除var声明的变量
b = 20; delete b; console.log(b); //删除成功,所以打印b的值:报错-->表示变量未声明 var a = 10; console.log(delete a); // false (静默错误) console.log(a); // 10 //未使用var声明的变量是全局变量, 会成为window的属性 b.dex = 'dex'; console.log(b.dex); // und delete b.dex; console.log(delete b.dex); // true console.log(b.dex); // 报错
可以删除直接定义在window上的属性
-
调试工具的使用
- 快捷键 F12
- Console的运行环境和js页面的环境是一样的
异常处理
- 在正常情况下, 代码如果出现了错误/异常, 该行代码后面的代码不会执行
- 即使代码出现错误, 后面的代码还是可以正常执行
- 手动抛出异常
throw+异常信息(对象/字符串)
- 手动抛出异常
try{
//处理可能会出错/异常代码
}catch(error){
//try的代码出错就执行, 并把捕获的错误信息抛出
}finally{
//此括号中代码与写在下面无区别, 释放一下不再使用的资源-后端使用
//不管try里面的代码是否出错, 都会执行此括号里的代码
}
面向对象/面向过程编程
- 相同点: 都是解决问题的一种思想
- 不同点: 解决问题的关注点不同.
- 面向对象关注解决问题所需的对象.
- 提高代码的复用性, 代码结构易于阅读, 扩充性维护性更好
- 面向过程关注解决问题 过程中的步骤.
- 面向对象关注解决问题所需的对象.
this
- 特殊情况
在事件指令中, this指向事件源
-
在定时器中, this指向window
//若想在定时器里拿到事件源的this btn.onclick = function () { var that = this; //备份指针,this指向btn window.setInterval(function () { console.log(that); },10); }
- 一般情况
this所在的函数是哪个对象, 就指向哪个对象
-
所有的全局变量都是window的属性, 所有的全局函数都是window的方法(参考W3C)
(function(){ var that = this; //this指向window setInterval(function(){ console.log(that) }, 30); })();
面向对象
对象拥有属性和方法
创建对象:
var obj = new Object()
-
函数创建对象常用写法
function person(){ var obj= new Object(); obj.name = 'Marry'; obj.age = 12; return obj; } person(); //创建了一个Marry对象 //创建另一个对象 var Jame = person(); Jame.name = 'Jame'; Jame.age = 14;
通过构造函数创建对象
定义: 构造函数就是一个函数, 用来初始化一个对象(给对象赋初始值), 一般与
new
关键字连用-
构造函数名称: 首字母大写
var obj = new Object() var dog = new Dog('wangcai', 1) //如下
-
this
所在的函数是哪个对象, 就指向哪个对象function Dog(name1, age1){ //new默认(内部实现)创建一个新的对象-默认把这个对象赋值给this //var obj = new Object(); //this = obj; //自定义属性 this.name = name1; this.age = age1; this.eat = function(sth){ console.log(this.name+'eat'+sth); //new默认(内部实现)返回新创建的对象 //return obj; } } var dog = new Dog('wangcai', 1); //问题: 创建多个对象时(dog1.eat==dog.eat), 对象中某些方法的实现是一样的, 但每创建一个对象都会创建一个新的函数, 会造成内存资源浪费 //优化-减少定义的形参 function Dog(option){ //判断外界是否传实参 var option = option || {}; this.name = option.name1; this.age = option.age1; this.eat = function(sth){ console.log(this.name+'eat'+sth); } } var dog = new Dog({name:'wangcai', age:1});
-
可以使用原型属性prototype-开发中常用
//第一种写法 Dog.prototype.eat = function(sth){ console.log(this.name+'eat'+sth); } //第二种写法 Dog.prototype = { eat:function(){ console.log(this.name+'eat'+sth); } } //_init是一个系统的初始化函数, 只要通过构造函数创建对象就会默认调用