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
nullundefined 其他非nullundefined的任意类型 不转换总是返回false
原始类型:stringnumberboolean Date对象 将原始类型转换为数字;将Date对象转换为原始类型(优先尝试toString()方法,再尝试valueOf()方法)
原始类型:stringnumberboolean Date对象 将原始类型转换为数字;将Date对象转换为原始类型(优先尝试valueOf()方法,再尝试方法toString())
原始类型:stringnumberboolean 原始类型:stringnumberboolean 将原始类型转化为数字

可以看出,== 运算符应用的这一套转换规则很难理解,因此最好显示地定义转换的逻辑再进行===判断

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对象

第2章 变量作用域

8、尽量少用全局变量


Comments
Write a Comment