Effective JavaScript
发布于 2016-08-11 20:52 阅读数 150
本文必须得到作者授权后,方可转载,摘要引流随意。
By 依韵 , From https://blog.cdswyda.com/post/20160811
第1章 让自己习惯JavaScript
1、版本
严格模式
"use strict"
2、JavaScript浮点数
数值类型都为number(64位编码数字,即doubles) -2^53到2^53 进行位运算时将其转换为了32位整数进行计算
最关键的地方,浮点数不精确
在有浮点数参与的运算中不能保证(x+y)+z=x+(y+z)
比如
1 2 | (0.1+0.2)+0.3;//0.6 000 000 000 000 001
0.1+(0.2+0.3);//0.6
|
解决方法 尽可能使用整数进行数学运算
3、当心隐式的强制转换
JavaScript在进行运算的时候会自动会操作数进行相应的转换。
特殊的是Null和NaN Null在算术运算中被转化为0 而未定义的变量量会被转换为NaN(Not a Nubmer)
NaN不等于其本身,函数库中的IsNaN也不可靠
1 2 3 4 5 6 7 | var x = NaN;
x === NaN; //false
IsNaN("foo"); //true
IsNaN(undefined); //true
IsNaN({}); //true
IsNaN({ a: 1 }); //true
|
不过NaN是JavaScript中唯一一个不等于其本身的值,所以可以利用这一点来测试一个值是不是NaN
1 2 3 4 5 6 7 8 | var a = NaN;
a !== a; //true
var b = undefined;
b !== b; //false
var c = {};
c !== c; //false
var d = { a: 1 };
d !== d; //false
|
还有对象隐式地调用toString方法进行转换为字符串或者valueOf方法转化为数字
4、原始类型优于封装对象
5、避免对混合类型使用 == 运算符
- == 运算符的转换规则
参数类型1 | 参数类型2 | 强制转换 |
---|---|---|
null |
undefined |
不转换总是返回true |
null 或undefined |
其他非null 和undefined 的任意类型 |
不转换总是返回false |
原始类型:string 、number 或boolean |
Date 对象 |
将原始类型转换为数字;将Date对象转换为原始类型(优先尝试toString()方法,再尝试valueOf()方法) |
原始类型:string 、number 或boolean |
非Date 对象 |
将原始类型转换为数字;将Date对象转换为原始类型(优先尝试valueOf()方法,再尝试方法toString()) |
原始类型:string 、number 或boolean |
原始类型:string 、number 或boolean |
将原始类型转化为数字 |
可以看出,== 运算符应用的这一套转换规则很难理解,因此最好显示地定义转换的逻辑再进行===判断
6、理解分号插入的局限
有的地方可以省略分号,我们需要知道JavaScript的分号插入规则。
有以下三条规则:
分号仅在
|
标记之前、一个或多个换行之后和程序输入的结尾被插入。
分号仅在随后的输入标记不能被解析时插入。(纠错机制)
分号不会作为分隔符在for循环空语句的头部被自动插入。
1 2 3 4 5 6 7 8 9 10 | for (var i =0 ,total = 1 //parse error
i < n
i++ ){
//TODO
}
// 即for头部必须显示地使用分号
//
// 空的while循环体也需要显式的分号
function infiniteLoop() { while (true) } //parse error
function infiniteLoop() { while (true); }
|
7、视字符串为16位代码单元
Tips:
- JavaScript字符串由16位的代码单元组成,而不是Unicode代码点组成。
- JavaScript使用两个代码单元表示216及以上的Unicode代码点。这两个代码单元被称为代理对。
- 代理对甩开了字符串元素计数、length、charAt、charCodeAt方法以及正则表达式模式(例如'.'不一定能匹配任意字符)。
- 使用第三方的库编写可识别代码点的字符串操作。
1 2 3 4 5 6 | /^.$/.test('ஷ');
true
/^.$/.test('𠮷');
false
/^..$/.test('𠮷');
true
|
上面展示了“.”不一定能匹配任何字符,因为在JavaScript中有的字符是用两位的代码单元表示的,比如上面的“𠮷”,其Unicode为0x20BB7,大于JavaScript中最大支持的0xFFFF,需要拆分表示。
1 | String.fromCharCode(0x20BB7);//"ஷ"
|
上面代码返回字符的编号是0x0BB7,而不是0x20BB7。它的根本原因在于,码点大于0xFFFF的字符占用四个字节,而JavaScript只支持两个字节的字符。这种情况下,必须把0x20BB7拆成两个字符表示。
1 | String.fromCharCode(0xD842, 0xDFB7);// "𠮷"
|
上面代码中,0x20BB7拆成两个字符0xD842和0xDFB7(即两个两字节字符,合成一个四字节字符),就能得到正确的结果。码点大于0xFFFF的字符的四字节表示法,由UTF-16编码方法决定。
可以参考阮一峰JavaScript标准参考教程String对象