额,以下是自己对这篇文章的翻译和理解,有理解不正确的地方还请各位大佬指出。
文章github地址
自己的地址:
WTF JavaScript
---
JavaScript是一种伟大的语言。 它有一个简单的语法,大的生态系统,最重要的是一个伟大的社区。
与此同时,我们都知道,JavaScript是一个非常搞笑的语言并且也有着棘手的部分。 有些可以迅速把我们的日常工作变成如入地狱般,有些又可以让我们笑出声来。WTFJS的最初想法属于Brian Leroux。 这些目录是通过他在2012年dotJS上的讲话“WTFJS”受到的高度启发:
Node Packaged Manuscript
----------------------------你可以安装使用手册,只要npm install -g wtfjs
现在你可以在命令行运行wtfjs,它将在手册中打开你选择的页面。你也可以在这里进行阅读。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
> 这里其实是一系列的比较,首先是比较右边的![],因为[]是个空数组,![]就是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 // -> falsenull == 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 // -> truetypeof document.all // -> 'undefined'
同时,它并不等于自定义
document.all === undefined // -> falsedocument.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 nullclass 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 // -> 3a.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() // -> 0Number(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以上只是其中的一部分,后续的一部分我也会慢慢整理出来。