位操作符
ECMAScript所有数字都以IEEE-754 64位格式存储,操作符先将64位转为32位整数,然后执行操作,其中第32位为符号位(正数0负数1)
正数直接转二进制存储,负数求正数二进制补码

Number.toString(2)负数表示直接正数二进制加负号
const a = -3;
console.log(a.toString(2));//-11

NaN和Infinity值应用位操作,被当作0处理
- 按位非(NOT) 返回数值的反码 【~数值】 本质就是操作数的负值-1
- 按位与(AND) 【数值&数值】

- 按位或(OR) 【数值|数值】

- 按位异或(XOR)【数值^数值】

- 左移 【数值<<位数】 将二进制左移一定位数,左移不会影响符号位,只是正数左移并增加负号
// 2 -> 10 -> 10 0000 -> 32
console.log(2<<4);//32
console.log(-2<<4);//-32
- 有符号右移 【数值>>位数】右移空出的位置以符号位填充(正数填充0负数填充1) 恰好与左移相反
console.log(32>>4);//2
console.log(-32>>4);//-2
- 无符号右移 【数值>>>位数】右移空出位置以0填充
基本类型转换和运算规则
boolean

Number
后面的数值操作符都基于此处规则

String
- 有toString方法直接调用
- null和undefined返回"null"和"undefined"
乘号
- number * number 常规,超出范围±Infinity
- 其中一个NaN,返回NaN
- Infinity * 0,返回NaN
- Infinity * 非0,返回Infinity
- Infinity * Infinity,返回Infinity
- 有一个不是数值则调用Number()规则转为数值再应用上面规则
除号
- number * number 常规,超出范围±Infinity
- 其中一个NaN,返回NaN
- Infinity / Infinity,返回NaN
- 0 / 0,返回NaN
- 0 / 非零有限数,返回Infinity或-Infinity
- 非零有限数 / Infinity,返回Infinity
- 有一个不是数值则调用Number()规则转为数值再应用上面规则
求余
- number % number 常规
- Infinity % number,返回NaN
- number % 0,返回NaN
- Infinity % Infinity,返回NaN
- number % Infinity,返回number
- 0 % anyNumber,返回0
- 有一个不是数值则调用Number()规则转为数值再应用上面规则
求和
- NaN + any,返回NaN
- Infinity + Infinity,返回Infinity
- -Infinity + -Infinity,返回-Infinity
- Infinity + -Infinity,返回NaN
- +0 + +0,返回+0
- -0 + -0,返回-0
- +0 + -0,返回+0
- string + string,字符拼接
- string + any, String(any) 字符拼接 详情见其他转字符串
减法
- number - number 常规
- 有一个NaN,返回NaN
- Infinity - Infinity,返回NaN
- -Infinity - -Infinity,返回NaN
- Infinity - -Infinity,返回Infinity
- -Infinity - Infinity,返回-Infinity
- +0 - +0,返回+0
- -0 - -0,返回-0
- +0 - -0,返回-0
- 有一个不是数值则调用Number()规则转为数值再应用上面规则
关系操作符规则
- 都是数值则比较大小
- 都是字符串,则比较字符编码
- 一个数值则另一个转换成数值再比较
- NaN和任何比较都是false
== 操作符比较流程
- 如果有一个为bool则先把bool转为数值再比较
- 有一个是对象另一个不是,则调用对象valueOf,再比较
- null和undefined相等(undefined派生自null)
- 有一个是NaN,则==返回false,!=返回true
- 对象和对象比较,内存一样返回true否则返回false
条件语句
- 条件语句先调用Boolean()将其他类型转为bool
- for循环执行判断并走完循环体再执行后面的运算
- for...in循环对象无序性,各执行环境输出顺序不一样
- 熟悉break,continue,label
- switch用的是===与case比较,不存在隐式转换
三个基本包装类型
Number,String,Boolean
const a = 'abc';
a.substring(1);
// 相当于下面
const a = 'abc';
const b = new String(a);
b.substring(1);
//删除b
延长作用域链
- with语句,将代码作用域设定到特定的对象
with(location){
// 局部环境找不到定义,就会去location找同名属性
const hostName = hostName;
const qs = search.substring(1);
const url = href;
}
- try-catch语句的catch块IE8及其之前catch捕获的错误对象catch外部可以访问到,现在已被修复
垃圾收集
- 标记清除:垃圾收集器在运行的时候给存储在内存中的所有变量都加上标记(可以用任何标记方式),然后去掉环境中的变量以及被环境中的变量引用的变量的标记。而在此之后再被加上标记的标量被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量,最后完成清楚工作,销毁那些带标记的值并回收它们所占用的内存空间
- 引用计数:跟踪记录每个值的被引用的次数,当某个值的被引用次数变为0,则垃圾收集器下次再运行时,就会释放那个引用次数为0的值所占用的内存,为了避免循环引用,用完记得赋值null
Array.prototype.sort
第一个参数位于第二个之前则返回负值,相等则返回0,否则返回1
const arr = [
{id: 2,age: 4},
{id: 1,age: 2},
{id: 3,age: 4},
{id: 2,age: 5},
{id: 3,age: 3},
{id: 1,age: 1},
]
arr.sort((a, b)=>{
// id升序
if(a.id > b.id) return 1;
if(a.id < b.id) return -1;
// age升序
if(a.age > b.age) return 1;
if(a.age < b.age) return -1;
return 0;
})
console.log(arr)
// [
// { id: 1, age: 1 },
// { id: 1, age: 2 },
// { id: 2, age: 4 },
// { id: 2, age: 5 },
// { id: 3, age: 3 },
// { id: 3, age: 4 }
// ]
callee和caller
- callee:一个指针,指向拥有该arguments对象的函数
function factorial(n){
if(n <= 1) return 1;
return n * arguments.callee(n - 1);
}
console.log(factorial(5))
- caller:该属性保存着调用当前函数的函数的引用
function b(){
a()
}
function a(){
console.log(a.caller === b)
}
b()//true
对象
对象的访问器和数据属性
- 访问器属性:get,set,configurable,enumerable
- 数据属性:writable.value,configurable,enumerable
new操作符
- 创建一个新对象
- 将构造器函数的作用域赋给新对象,即this
- 返回对象
概念
- prototype:每个函数都有prototype属性,这是一个指针,指向一个对象,该对象用途是包含可以由特定类型的所有实例共享的属性和方法
- 闭包:有权访问一个函数作用域中的变量的函数,理解执行环境的创建及作用域链和活动对象
- 作用域链:本质是一个指向变量对象的指针列表,它只引用但不实际包含变量对象
- this:this对象是运行时基于函数的执行环境绑定的,在全局函数中,this等于window,当函数被作为某个对象的方法调用时,this等于那个对象,匿名函数的执行环境具有全局性,因此this通常指向window