译者按: JavaScript有不少坑,常常一不当心就要写bug。javascript
为了保证可读性,本文采用意译而非直译。另外,本文版权归原做者全部,翻译仅用于学习。html
JavaScript是一门伟大的语言,它拥有很是简洁的语法,庞大的生态系统,以及最重要的:有一个伟大的社区支撑着。同时,咱们也知道JavaScript是一个充满技巧性的语言。有些坑足以让咱们崩溃,也有些奇淫技巧让咱们以为颇有趣。本文的思想源自于Brian Leroux在dotJS2012上的演讲“WTFJS” at dotJS 2012。前端
<div style="text-align: center;">
<img style="width:80%;" src="javascript-werid-series-1/brian.jpeg" />
</div>java
我收集这些例子的主要目的是将它们整理并清楚理解它们的原理。从中学到不少之前不懂的知识是一件颇有趣的事情。若是你是初学者,你能够经过学习这些笔记深刻理解JavaScript;若是你是一个专业的开发者,那么能够将这些笔记做为一个不错的引用资料。无论怎样,只要读下去,你就会学到新东西的。git
[ ] == ![ ] // -> true
相等(==)判断操做会将两边的类型都转换为数字(number),而后再比较。由于[]
和![]
都会转换为0
。咱们能够理解[]
是一个数组,只不过为空而已,那么为true。右侧![]
则为false。false而后转换为数字0。左侧[]
直接转换为数字,由于空数组会转换为0
,因此尽管咱们认为[]
为true,这里却变成了0
。github
下面是简化的计算过程:算法
+[] == +![] 0 == +false 0 == 0 true
参考:数组
!!'false' == !!'true' // -> true !!'false' === !!'true' // -> true
true是一个真值,用1表示;字符串的“true”
则为NaN。浏览器
true == 'true' // -> false false == 'false' // -> false
'false'是一个有意义的字符串。less
!!'false' // -> true !!'true' // -> true
参考:7.2.13 Abstract Equality Comparison
'b' + 'a' + + 'a' + 'a' // -> baNaNa
这是一个旧笑话,不过改进过的。原始的长这样:
'foo' + + 'bar' // -> 'fooNaN'
该表达式以'foo' + (+'bar')
的形式计算,由于bar
不是数字,因此转换为NaN。
参考:
NaN === NaN // -> false
根据===
的算法,咱们能够容易理解为何为false。
若是typeof(x)和typeof(y)不一样,那么返回false.
不然,若是typeof(x)是Number,那么
- 若是x是NaN,那么返回false;
- 若是y是NaN,那么返回false;
- ...
由此能够得出值为false的结论。
(![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]] // -> fail
若是咱们仔细观察序列的规律,会发现下面的模式出现不少次:
(![]+[]) // -> 'false' ![] // -> false
所以,咱们尝试将[]和false相加。可是根据内部一些列函数的计算(binary + Operator -> ToPrimitive -> [[DefaultValue]]),右侧的[]最终转换为string:
(![]+[].toString()) // 'false'
对于一个字符串,咱们就能够经过下标来获取对应的字符:
'false'[0] // -> 'f'
剩下的都很直观,除了i
很取巧。fail
中的i
是经过在falseundefined
中获取第十个下标对应的字符而获得。
空数组不等于true。(An array is a truthy value, however, it's not equal to true.)
!![] // -> true [] == true // -> false
参考:
尽管null是一个false的值,可是null不等于false。
!!null // -> false null == false // -> false
不过,若是和其它false的值比较,那么他们又是相等的。
0 == false // -> true '' == false // -> true
参考: 7.2.13 Abstract Equality Comparison
JavaScript坑不少,赶忙使用fundebug扶一扶!
⚠️这个是前端浏览器API,在Nodejs环境没法使用。
尽管document.all能够返回一个像数组同样的对象,能够用来访问DOM节点。可是呢,经过typeof查看document.all,你会惊讶地发现类型是undefined
。
document.all instanceof Object // -> true typeof document.all // -> 'undefined'
并且,document.all并不等于undefined。
document.all === undefined // -> false document.all === null // -> false
并且,更惊讶的是:
document.all == null // -> true
document.all是一个过去经常使用的获取DOM元素的方法,特别是老版本的IE。可是从未进入标准,尽管普遍使用在过去的JS代码中。当新的API突出来(好比document.getElementById)后,document.all就被淘汰了。标准委员会不得不以为怎么处理它。但是由于它已经被普遍使用,因此委员会以为保留它,可是违背了JavaScript的规范。
参考:
Number.MIN_VALUE
是最小的数,可是它比0还大。
Number.MIN_VALUE > 0 // -> true
由于Number.MIN_VALUE
是5e-324
。也就是说即便最小的值也能够用浮点数表示出来,虽然离0很接近,可是依然比0大。其实最小的数是Number.NEGATIVE_INFINITY
,尽管它不是一个实际存在的数。
在StackOverflow有相关问题:Why is 0 less than Number.MIN_VALUE in JavaScript?。