数据类型
null, undefined
- null 是空值,即初始时表示值为空,之后再赋值
 - undefined 是 未定义
 
1  | null + 4 // 4  | 
布尔值
- 基础数据类型自动转换为
false:1
2
3
4
5
60
NaN
""
false
undefined
null - 空数组和对象: 
true 
数值
- NaN不等于任何值:
NaN !== NaN 0/0 // NaN- Infinity大于一切数值(除了NaN),-Infinity小于一切数值(除了NaN)
 0 * Infinity // NaN
Number()
1  | Number([]) // 0  | 
parseInt
1  | parseInt('+') // NaN  | 
isNaN()
1  | // 只对数值有效,如果传入其他值,会被先转成数值  | 
对象
属性
所有键名(key/也称为属性property或方法) 都是字符串(也有Symbol), 所以加不加引号都行:
1
2
3
4
5
6
7
8
9var obj = {
1: "a",
3.3: "b",
<!-- 不符合标识名的条件 -->
"1p": "必须加引号"
}
obj[1] == "a"
obj["1"] == "a"变量指向对象,是指向了一个内存地址。
- 不同的变量名指向同一个对象,那么它们都是这个对象的引用
 - 取消某一个变量对于原对象的引用,不会影响到另一个变量
 
点运算符:直接表示字符串属性,不需加引号。
※ 数字属性不能用点运算符
方括号运算符: 需要加引号,否则识别成一个变量
obj["foo"] !== obj[foo]删除属性:
delete obj.p // true无法删除继承的属性
只有configurable: false时,返回false
判断是否为自身属性
obj.hasOwnProperty('toString')) // false'toString' in obj // truefor (var p in obj)遍历可遍历(enumerable)的属性,跳过不可遍历的属性
自身的和继承的都显示
函数
函数定义
- 采用function命令声明函数会提升。赋值语句定义函数不会
 - 具名函数只能在函数内部调用, 赋值后就没有意义
name属性会返回具名函数function字段后的名称1
2var f3 = function myName() {};
f3.name // 'myName'
 
函数的作用域
作用域与变量一样, 就是其声明时所在的作用域,与其运行时所在的作用域无关。
形成闭包现象
1
2
3
4
5
6
7
8
9
10var a = 1;
var x = function () {
console.log(a);
};
function f() {
var a = 2;
x();
}
f() // 1与传入参数不同
1
2
3
4
5
6
7
8
9
10var a = 1;
var x = function (a) {
console.log(a);
};
function f() {
var a = 2;
x(a);
}
f() // 2
参数
- 传入基础类型是值传递, 不会改变全局的值
 - 传入对象是地址传递,更改形参的属性,实参的属性也会变。
如果替换掉整个参数,这时不会影响到原始值
∵ 将形参指向了另一个地址,故不会改变原地址的内容 
同名参数
- 取最后出现的那个值。
1
2
3
4function f(a, a) {
console.log(a);
}
f(1) // undefined 
arguments
callee
- 返回它所对应的原函数
 
闭包
1  | function f1() {  | 
- 闭包就是函数f2: 能够读取其他函数内部变量的函数
 - 其两大特点:
- 可以读取函数内部的变量另一个就是
 - 让这些变量始终保持在内存中,即闭包可以使得它诞生环境一直存在
 - 封装对象的私有属性和私有方法
 
 
数组
不推荐用 for in
- 不仅遍历数字属性,还遍历非数字键
 
空位 和 undefined 区别
delete删除某位后形成空位, 对length没有影响:[,,,]- 空位都会被跳过: 
forEach方法、for...in结构、以及Object.keys方法进行遍历 undefined不会跳过:[undefined,undefined,undefined]
运算符:相加
布尔值
- 布尔值转换为数值
- 俩布尔值相加
 - 布尔值 和 数值相加
 
 
字符串
- 从左到右依次决定是 连接 还是 相加
 
1  | '3' + 4 + 5 // "345"  | 
对象
- 必须先转成原始类型的值,然后再相加:
obj + 2 // "[object Object]2"是因为调用了
valueOf得到对象本身,再调用toString得到[object Object]
特例:如果运算子是一个Date对象的实例,那么会优先执行toString方法 
其余运算符 - * /
- 一律转为数值
 
数据类型转换
Number 同上
null转为数值时为0,而undefined转为数值时为NaN
String
基础类型
- 转换为对应的字符串形式
 
对象
1  | String({a: 1}) // "[object Object]"  | 
自动转化
- 先将复合类型的值转为原始类型的值,再将原始类型的值转为字符串
1
2
3'5' + {} // "5[object Object]"
'5' + [] // "5" ∵ [] 为空
'5' + function (){} // "5function (){}" 
Boolean
1  | // Boolean() 返回false  | 
Error
new Error(message)配合name 和 stack使用
1  | function f() {  | 
Object 对象
- Object对象本身的方法: 被Object直接使用 
Object.print() - Object的实例方法: 定义在Object原型对象
Object.prototype上的方法, 被Object的实例直接使用var obj = new Object(); obj.print()- obj 是一个实例,继承了
Object.prototype的属性和方法 
 - obj 是一个实例,继承了
 
Object()函数
- 保证其是Object
- null/undefined: 返回空对象
 - 数/字符串/boolean: 
obj instanceof Object // true+obj instanceof Number // true - 对象/数组/函数:不转换,返回原对象/数组/函数
 
 - 区别于 
new Object()构造函数 
Object 静态方法
Object.keys 和 Object.getOwnPropertyNames
Object.keys方法返回自身的(而不是继承的)所有属性名,只返回可枚举的属性。Object.getOwnPropertyNames返回对象自身的所有属性名,还返回不可枚举的,例如:length
Object 实例方法
Object.prototype.valueOf()Object.prototype.toString()等
obj.hasOwnProperty
- 实例对象自身是否具有该属性。 
toString // false 
判断类型
Object.prototype.toString.call(value):- 函数:返回
"[object Function]" - 数值:返回
"[object Number]" - Error 对象:返回
"[object Error]" - RegExp 对象:返回
"[object RegExp]" - 其他对象:返回
"[object Object]" 
- 函数:返回
 
数组
- 一般不用 
new Array()语法,有歧义1
2
3
4
5
6
7// 单个正整数参数,表示返回的新数组的长度
new Array(1) // [ empty ]
new Array(2) // [ empty x 2 ]
// / 多参数时,所有参数都是返回的新数组的成员
new Array(1, 2) // [1, 2]
new Array('a', 'b', 'c') // ['a', 'b', 'c'] 
静态方法
Array.isArray(): 弥补 typeof 的不足
包装对象
new Number()new String()new Boolean()生成的是对象,与原数字/字符串/布尔值 不相等
Date对象
普通函数用法
- 不管有没有参数:返回一个代表当前时间的字符串
 
构造函数
1  | // 参数为时间零点开始计算的毫秒数  | 
面向对象编程
new 命令
- 原理:
- 创建一个空对象,作为将要返回的对象实例。
 - 将这个空对象的原型,指向构造函数的prototype属性。
 - 将这个空对象赋值给函数内部的this关键字。
 - 开始执行构造函数内部的代码。
 
 
Object.create()
- 创建实例对象: 在没有构造函数的情况下,利用现有的对象生成新的实例对象