额,以下是自己对这篇文章的翻译和理解,有理解不正确的地方还请各位大佬指出。
文章github地址 https://github.com/denysdovhan/wtfjs
自己的地址: https://www.zybuluo.com/phone/note/916113
WTF JavaScript
---
JavaScript是一种伟大的语言。 它有一个简单的语法,大的生态系统,最重要的是一个伟大的社区。
与此同时,我们都知道,JavaScript是一个非常搞笑的语言并且也有着棘手的部分。 有些可以迅速把我们的日常工作变成如入地狱般,有些又可以让我们笑出声来。
WTFJS的最初想法属于Brian Leroux。 这些目录是通过他在2012年dotJS上的讲话“WTFJS”受到的高度启发:
Node Packaged Manuscript
----------------------------
你可以安装使用手册,只要
npm install -g wtfjs
现在你可以在命令行运行wtfjs,它将在手册中打开你选择的页面。你也可以在这里进行阅读。[阅读链接地址][1]
Motivation
----------
> Just for fun
— [“Just for Fun: The Story of an Accidental Revolutionary”][2], Linus Torvalds
这个列表主要的目的是去收集一些疯狂的例子,有可能的话也会解释它们是如何工作的。正因为如此我们能学到以前不了解的东西。
如果您是初学者,您可以使用这些注释来深入了解JavaScript。 我希望这些笔记会激励你花更多的时间阅读规范。
如果您是专业开发人员,您可以将这些示例视为对我们所爱的JavaScript的所有怪异和意想不到的边缘的极大参考。
无论如何,去阅读它吧,你有可能将会发现一些新东西。
Notation(符号说明)
------------
`//->`用于展示表达式的结果,例如:
1 + 1 // -> 2
`//>`表示console.log或者其他的输出,例如
console.log('hellow world') // > hellow world
`//` 这个相信大家都知道,是注释的意思 ,例如
//定义一个函数赋值给foo常量 const foo = function(){}
Examples
--------
[] 等于 ![]
[] == ![] // ->true
解释:
[12.5.9 Logical NOT Operator (!)][3]
[7.2.13 Abstract Equality Comparison][4]
> 这里其实是一系列的比较,首先是比较右边的![],因为[]是个空数组,![]就是false, 变成比较[]> ==false,根据es规范中的7.2.13节第七条,对号入座。 变成[] == ToNumber(false);根据7.1.3中的ToNumber()规则,变成[] == 0;
> 回到7.2.13的第九条,变成ToPrimitive([]) == 0;根据规则一步一步下去,结果就是 0 == 0 ,当然return true
**true is false**
!!'false' == !!'true' // -> true !!'false' === !!'true' // -> true
> 个人认为要区分字符串和布尔值就行了 'false'是非空的字符串
**baNaNa**
'b' + 'a' + + 'a' + 'a' // ->baNaNa
这是JavaScript中的一个老式的笑话,但是换了个版本。 这是原来的:
'foo' + + 'bar' // -> 'fooNaN'
> 给大家说说我理解的这个笑话:foo的意思是fu的变体,fu又是英语习语fuckup的缩写,bar是无法识别的意思。连在一起就是TMD无法识别。你和电脑说:请拼接下这个TMD无法识别,电脑:TMD
> NAN。。。。(哈哈哈哈。。。)
这个表达式实际是为'foo'+(+'bar'),它将'bar'转换为非数字。
解释:
[12.8.3 The Addition Operator (+)][5]
[12.5.6 Unary + Operator][6]
**NaN is not a NaN**
NaN === NaN // -> false
解释:
规范严格定义了这一行为背后的逻辑:
1.If Type(x) is different from Type(y), return false.
2.If Type(x) is Number, then
If x is NaN, return false.
If y is NaN, return false.
… … …[----- 7.2.14 Strict Equality Comparison][7]
**It's a fail**
你可能不相信
(![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]// -> 'fail'
解释:
通过将大量的符号分解成块,我们注意到经常出现以下模式:
(![]+[]) // -> 'false' ![] // -> false
所以我们尝试将[]添加为false。 但是由于一些内部函数调用(二进制+运算符 - > ToPrimitive - > [[DefaultValue]]),我们最终将右侧的操作数转换为一个字符串:
(![]+[].toString()) // 'false'
想像一个字符串作为一个数组,我们可以通过[0]访问它的第一个字符:
'false'[0] // -> 'f'
其余的就很明显,但是这个i很棘手,通过生成字符串“falseundefined”抓取不到index ['10']上的元素
**[] is truthy, but not true**
一个数组是有着真实的值,但是并不等于true
!![] // -> true [] == true // -> false
以下是ECMA-262规范中相应部分的链接:
[12.5.9 Logical NOT Operator (!)][8]
[7.2.13 Abstract Equality Comparison][9]
**null is falsy, but not false**
尽管null是一个错误的值,但它不等于false。
!!null // -> false null == false // -> false
同时,其他错误值,如0或“”等于false。
0 == false // -> true '' == false // -> true
解释:
> 也是一系列的比较,链接和上面的一样。
**document.all is an object, but it is undefined**
*这是浏览器的一个api,并不会在nodeJs环境下生效*
尽管document.all是一个类数组的对象,它可以访问页面中的DOM节点,但使用typeof函数的结果是未定义。
document.all instanceof Object // -> true typeof document.all // -> 'undefined'
同时,它并不等于自定义
document.all === undefined // -> false document.all === null // -> false
但相同的:
document.all == null // -> true
解释:
> document.all曾经是一种访问DOM元素的方式,与旧版本的IE相似。虽然它从来没有成为一种标准,但它在旧版JS代码中被广泛使用。当新的api被标准委员会提出(像document.getElementById),这个API调用的已经过时了,标准委员必须决定如何处理它。由于它的广泛使用,他们决定保留API,并故意使它违反JavaScript规范。这就是为什么当使用严格的比较对照的规则即“===”( [Strict Equality Comparison][10])时,结果是false。由于明确允许故意违规规范,所以在使用抽象的比较对照规则即“==”([Abstract Equality Comparison][11] )时结果为true
**Minimal value is greater than zero**
Number.MIN_VALUE 是最小的数字, 并且大于0:
Number.MIN_VALUE > 0 // -> true
解释:
Number.MIN_VALUE是5e-324,即可以在浮点精度内表示的最小正数,即尽可能接近于零。现在,整体最小的值是Number.NEGATIVE_INFINITY,尽管它在严格意义上并不是真正的数字。
**function is not function**
所有人都知道烦人的undefined不是一个函数,但是呢?
// Declare a class which extends null class Foo extends null {} // -> [Function: Foo] new Foo instanceof null // > TypeError: function is not a function // > at … … …
解释:
这不是规范的一部分。 这只是一个已经修复的错误,所以今后不应该有问题。
**Adding arrays**
如果你尝试将两个数组相加
[1, 2, 3] + [4, 5, 6] // -> '1,2,34,5,6'
解释:
一步步解析,像下面这样:
[1, 2, 3] + [4, 5, 6] // call toString() [1, 2, 3].toString() + [4, 5, 6].toString() // concatenation '1,2,3' + '4,5,6' // -> '1,2,34,5,6'
**Trailing commas in array**
您创建了一个包含4个空元素的数组。尽管如此,因为后面的逗号你会得到一个有三个元素的arrary:
let a = [,,,] a.length // -> 3 a.toString() // -> ',,'
解释:
在JavaScript代码中添加新元素,参数或属性时,逗号(有时称为“最终逗号”)很有用。如果要添加新的属性,如果前一行已经添加了逗号,那么不需要修改前一行,只需要添加新行即可。这使得版本控制差异更清晰,编辑代码可能不那么麻烦。
**Array equality is a monster**
数组比较是JS中的一个怪物。。。
[] == '' // -> true [] == 0 // -> true [''] == '' // -> true [0] == 0 // -> true [0] == '' // -> false [''] == 0 // -> true [null] == '' // true [null] == 0 // true [undefined] == '' // true [undefined] == 0 // true [[]] == 0 // true [[]] == '' // true [[[[[[]]]]]] == '' // true [[[[[[]]]]]] == 0 // true [[[[[[ null ]]]]]] == 0 // true [[[[[[ null ]]]]]] == '' // true [[[[[[ undefined ]]]]]] == 0 // true [[[[[[ undefined ]]]]]] == '' // true
解释:
你应该非常小心以上的例子!该行为在规范的7.2.13抽象平等比较部分进行了描述。
**undefined and Number**
如果我们没有将任何参数传递到Number构造函数中,我们将得到0.当没有实际参数时,将undefined赋值给形式参数,因此您可能希望Number(无参数)将undefined定义为其参数的值。但是,当我们通过undefined时,我们将得到NaN。
Number() // -> 0 Number(undefined) // -> NaN
解释:
根据以下的规范可以得出:
> 1.If no arguments were passed to this function's invocation, let n be +0.
> 2.Else, let n be ? ToNumber(value).
> 3.In case of undefined, ToNumber(undefined) should return NaN.
以上只是其中的一部分,后续的一部分我也会慢慢整理出来。
[1]: https://github.com/denysdovhan/wtfjs
[2]: https://en.wikipedia.org/wiki/Just_for_Fun
[3]: https://www.ecma-international.org/ecma-262/#sec-logical-not-operator
[4]: https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison
[5]: https://www.ecma-international.org/ecma-262/#sec-additive-operators
[6]: https://www.ecma-international.org/ecma-262/#sec-unary-plus-operator
[7]: https://www.ecma-international.org/ecma-262/#sec-strict-equality-comparison
[8]: https://www.ecma-international.org/ecma-262/#sec-logical-not-operator
[9]: https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison
[10]: https://www.ecma-international.org/ecma-262/#sec-strict-equality-comparison
[11]: https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison