Fork me on GitHub

《你不知道的Javascript中卷》中有趣的知识点一

最近在看《你不知道的Javascript中卷》,里面有不少有趣的知识点和新鲜货,在这里做一个分享

一、类数组转换

一些 DOM 查询操作会返回 DOM 元素列表,它们并非真正意义上的数组,但十分类似。另一个例子是通过 arguments 对象(类数组)将函数的参数,这时候我们可以通过如下方式将这些类数组转换为数组:

1
2
3
4
//通过工具函数slice();
var arr = Array.prototype.slice.call( arguments );
//或者ES6语法Array.from();
var arr = Array.from( arguments );

二、 . 运算符

对于 . 运算符我们需要给予特别注意,因为它是一个有效的数字字符,会被优先识别为数字常量的一部分,然后才是对象属性访问运算符。

1
2
3
4
5
6
7
// 无效语法:
42.toFixed( 3 ); // SyntaxError
// 下面的语法都有效:
(42).toFixed( 3 ); // "42.000"
0.42.toFixed( 3 ); // "0.420"
42..toFixed( 3 ); // "42.000"
42 .toFixed(3); // "42.000"(注意其中的空格)

三、0.1 + 0.2 === 0.3 ?

在js中:

1
0.1 + 0.2 === 0.3; // false

关于这个问题,感兴趣的同学可以读读王二的转载的一篇文章抓住数据的小尾巴 - JS浮点数陷阱及解法,由于 JavaScript 中的数字类型是基于 IEEE754 标准来实现的,所以二进制浮点数中的 0.1 和 0.2 相加并不是十分精确,这时候可以使用 Number.EPSILON 来比较两个数字是否相等(在指定的误差范围内):

1
2
3
4
5
6
function numbersCloseEnoughToEqual(n1,n2) { 
return Math.abs( n1 - n2 ) < Number.EPSILON;
}
var a = 0.1 + 0.2;
var b = 0.3;
numbersCloseEnoughToEqual( a, b ); //true

四、nullundefined

null 是一个特殊关键字,不是标识符,我们不能将其当作变量来使用和赋值。然而 undefined 却是一个标识符,可以被当作变量来使用和赋值。

五、isNaN()

我们可以使用全局工具函数 window.isNaN() 和 ES6中的 Number.isNaN() 来判断一个值是不是 NaN,但这两者也有区别,参考如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Number.isNaN( NaN ); // true
Number.isNaN( "wanger" ); // false
Number.isNaN( 5 ); // false

window.isNaN( NaN ); // true
window.isNaN( "wanger" ); // true
window.isNaN( 5 ); // false
```

很明显 "wanger" 不是一个数字 ,它也不是 NaN 。但是 `window.isNaN( "wanger" )`显示为true, 这个 bug自 JavaScript 问世以来就一直存在。

### 六、`Object.prototype.toString` 可以查看类型

```js
Object.prototype.toString.call( [1,2,3] ); // "[object Array]"
Object.prototype.toString.call( /regex-literal/i ); // "[object RegExp]"
Object.prototype.toString.call( null ); // "[object Null]"
Object.prototype.toString.call( undefined ); //"[object Undefined]"
Object.prototype.toString.call( "abc" ); // "[object String]"
Object.prototype.toString.call( 42 ); // "[object Number]"
Object.prototype.toString.call( true ); // "[object Boolean]"

七、JSON 字符串化

undefinedfunctionsymbol (ES6+)和包含循环引用(对象之间相互引用,形成一个无限循环)的对象都不符合 JSON 结构标准,支持 JSON 的语言无法处理它们。
JSON.stringify(..) 在对象中遇到 undefinedfunctionsymbol 时会自动将其忽略,在数组中则会返回 null(以保证单元位置不变)。

例如:

1
2
JSON.stringify([1,undefined,function(){},4]);   // "[1,null,null,4]"
JSON.stringify({ a:2, b:function(){} }); // "{"a":2}"

八、假值对象

先看一段代码:

1
2
3
4
5
console.log(document.all)  //会返回页面上的所有元素

if(document.all){
console.log("test") //不会答应 "test"
}

最常见的假值对象是 document.all ,它是一个类数组对象,包含了页面上的所有元素,由 DOM(而不是 JavaScript 引擎)提供
给 JavaScript 程序使用。它以前曾是一个真正意义上的对象,布尔强制类型转换结果为 true ,不过现在它是一个假值对象。

虽然 JavaScript 代码中会出现假值对象,但它实际上并不属于 JavaScript 语言的范畴。但这里仍然有必要注意一下。

需要注意的是,为我们经常通过将 document.all 强制类型转换为布尔值(比如在 if 语句中)来判断浏览器是
否是老版本的 IE,如下:

1
if(document.all) { /* it's IE */ }

九、显式解析数字字符串

解析字符串中的数字和将字符串强制类型转换为数字的返回结果都是数字。但解析和转换两者之间还是有明显的差别,参考如下代码:

1
2
3
4
5
6
7
var a = "42";
var b = "42px";

Number( a ); // 42
parseInt( a ); // 42
Number( b ); // NaN
parseInt( b ); // 42

解析允许字符串中含有非数字字符,解析按从左到右的顺序,如果遇到非数字字符就停止。而转换不允许出现非数字字符,否则会失败并返回 NaN

需要注意的是 parseInt() 针对的是字符串值。向 parseInt() 传递数字和其他类型的参数是没有用的,比如 truefunction(){...}[1,2,3],因为非字符串参数会首先被强制类型转换为字符串,所以如下的代码就没有问题:

1
parseInt( new String( "42") );  // 42

十、||&&

||&& 运算符的返回值并不一定是布尔类型,而是两个操作数其中一个的值,参考如下代码:

1
2
3
4
5
6
7
8
var a = 42;
var b = "abc";
var c = null;

a || b; // 42
a && b; // "abc"
c || b; // "abc"
c && b; // null

在 C 和 PHP 中,上例的结果是 truefalse ,在 JavaScript(以及 Python和 Ruby)中却是某个操作数的值。

十一、假值的相等比较

== 中的隐式强制类型转换最为人诟病的地方是假值的相等比较。

下面分别列出了常规和非常规的情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
"0" == null; // false
"0" == undefined; // false
"0" == false; // true -- 晕!
"0" == NaN; // false
"0" == 0; // true
"0" == ""; // false
false == null; // false
false == undefined; // false
false == NaN; // false
false == 0; // true -- 晕!
false == ""; // true -- 晕!
false == []; // true -- 晕!
false == {}; // false
"" == null; // false
"" == undefined; // false
"" == NaN; // false
"" == 0; // true -- 晕!
"" == []; // true -- 晕!
"" == {}; // false
0 == null; // false
0 == undefined; // false
0 == NaN; // false
0 == []; // true -- 晕!
0 == {}; // false

为了更详尽的展现假值的相等比较的一些特殊情况,github 上的@dorey做了一个JavaScript-Equality-Table如下图:

Alt text

其中绿色表示为 true ,白色表示为 false;

资源地址戳这里 密码:j9gp

-------------本文结束感谢您的阅读-------------