what the fuck javascript 你不知道的javaScript的怪癖(上)

前言

JavaScript是一种伟大的语言。它有一个简单的语法,大的生态系统,最重要的是一个伟大的社区。
同时,我们都知道JavaScript是一个非常有趣的语言特性。他们中的一些可以迅速将我们的日常工作变成地狱,有些可以让我们大声笑起来。
WTFJS的最初想法属于Brian Leroux。该清单受到他在2012年dotJS上的演讲“WTFJS”的高度启发:

这篇文章主要是收集一些奇奇怪怪的例子,并解释他是如何工作的。如果你是初学者,您可以使用这些注释来深入了解JavaScript。我希望这些笔记会激励你花更多的时间阅读规范。如果您是资深的开发人员,您可以将这些示例视为对我们所爱的JavaScript的所有怪癖和意想不到的地方的参考内容。

无论如何,只要读了这篇文。你可能会找到新的东西。
查看原文

Example

[] is equal ![]

[]==![] //true 

相等运算符的比较有指定的规则,

1.如果其中一个值是true,则将其转换为1再进行比较。如果其中一个值是false,则将其转换为0再进行比较。

2.如果一个值是对象,另一个值是数字或字符串,则将对象转换为原始值再进行比较。对象通过toString()方法或valueOf()方法转换为原始值。JavaScript语言核心的内置类首先尝试使用valueOf(),在尝试使用toString(),除了日期类,日期类只使用toString()方法,那些不是JavaScript语言核心中的对象则通过各自实现中定义的方法转换为原始值。

![] 为布尔值,根据第一条规则,先转换为数值0。这时为空数组和数字0的比较。根据第二条,空数组优先调用valueOf()方法,空数组转换为空字符串;如果一个值为字符串、一个为数字,将字符串转化为数字进行比较。

true is false

!!'false' ==  !!'true'  // -> true
!!'false' === !!'true' // -> true

这是因为!跟一个字符串都将他转换为布尔值,所以不论是!'fasle'还是!'true'都是fasle,再取反即为true.

baNaNa

'b' + 'a' + + 'a' + 'a' // -> "baNaNa"
'foo' + + 'bar' // -> 'fooNaN'

在对非数值应用一元加操作符时,该操作符会像Number()转型函数一样对这个值进行转换。布尔值会被转换为0/1,字符串根据相应的规则进行转换,对象调用valueOf()和(或)toString()方法,再转换得到的值。

'b' + 'a' + + 'a' + 'a''foo' + (+'bar')等价。根据以上一元加操作符的规则,Number('bar')转换为NaN。再进行'foo'+NaN,如果有只有一个操作符为字符串,则将另一个操作符转换为字符串,调用toString()方法,进行拼接。

NaN is not a NaN

NaN === NaN // -> false

因为任何涉及到NaN的操作,都会返回NaN。NaN与任何值都不相等,包括NaN本身。
在IEEE中,是这样定义NaN的:

存在四种相互排斥的关系:小于,等于,大于和无序。当至少有一个操作数是NaN时,最后一种情况出现。每个NaN都要比较无穷无尽的一切,包括自己。

所以,NaN!==NaN为true。

It's a fail

你可能不相信,但OVO

    (![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]
// -> 'fail'

先把大串符号分解成碎片,会以下的模式经常出现

![]      // -> false
(![]+[]) // -> 'false'
[][[]] // -> undefined
[![]]+[][[]] // -> 'falseundefined'

对于加性操作符,如果有一个操作数是对象、数值或布尔值,则调用toString()方法取得相应的字符串,再应用前面的关于字符串的规则。

![]是个布尔值,根据以上规则,[].toString()为空字符串,拼接起来为字符串false。

[+[]] // -> [0]
(![]+[])[+[]] // -> 'f'
[+!+[]] // -> [1]
(![]+[])[+!+[]] // -> 'a'
[]+[+[]] // -> '0'
+!+[] // -> 1
+!+[]+[]+[+[]]  //-> '10'
([![]]+[][[]])[+!+[]+[+[]]] // -> 'i'
!+[]+!+[] // true+true -> 2
(![]+[])[!+[]+!+[]] // 'l'

[] is truthy, but not true

数组是一个真实的值,但并不等于true

!![]       // -> true
[] == true // -> false

对于相等操作符来说,先将操作数强制转型,再进行比较。
当一个操作数为布尔值时,先将他转换为数值,false->0,true->1。
一个操作数为字符串,一个为数值时,将字符串转换为数值。
一个为对象,另一个不是对象,调用valueOf()方法,按照前面的规则进行比较。

[]转换为0,true转换为1,所以[] == true为fasle

null is falsy, but not false

尽管null是一个falsy,但它不等于false

!!null        // -> false
null == false // -> false

同时,其他的falsy,如0或“”等于false。

0 == false  // -> true
'' == false // -> true

这是因为,在比较相等性之前,不能将null和undefined转换成其他任何值。null和undefined是相等的。

Minimal value is greater than zero 最小值大于0

Number.MIN_VALUE > 0 // -> true

Number.MIN_VALUE是5e-324,5*10的-324次幂。

Adding arrays

你试过将两个数组相加吗

[1, 2, 3] + [4, 5, 6]  // -> '1,2,34,5,6'

这是因为在相加的时候调用了toString()[1,2,3]转换为1,2,3[4,5,6]转换为4,5,6,然后拼接起来为1,2,34,5,6

Trailing commas in array 数组中的尾随逗号

您创建了一个包含4个空元素的数组。尽管如此,你会得到一个有三个元素的数组

let a = [,,,]
a.length     // -> 3
a.toString() // -> ',,

在javascript中,当添加一个元素、参数或属性时,尾随逗号(有时又被称作最后的逗号)很有用。如果要添加新的属性,只需添加新行即可,如果该行已经使用了一个逗号,那么不修改之前的最后一行。如果要添加新的属性,只需添加新行即可,如果该行已经使用了一个逗号,那么不修改之前的最后一行。

Array equality is a monster

[] == ''   // -> 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

因为在强制转型时,调用toString()方法,以上示例的数组都被转换为空字符串,在比较时转换为0.

undefined and Number

如果我们没有将任何参数传递给Number构造函数,我们将得到0。当没有实际参数时,undefined被分配给形式参数,所以你可能认为没有参数的Number将不定义为其参数的值。但是,当我们传递undefined时,将得到NaN。

Number()          // -> 0
Number(undefined) // -> NaN

对于Number()方法,传入布尔值,true和fasle会被转换为1/0;传入null,返回0;传入undefined,返回NaN;如果是字符串将根据特殊规则进行转换;如果是对象,调用valueOf()方法,按照前面的规则进行转换,如果返回值为NaN,则调用对象的toString()方法,再次按照前面的规则转换返回的字符串值。

parseInt is a bad guy

parseInt是因为它的怪癖算法所闻名的

parseInt('f*ck');     // -> NaN
parseInt('f*ck', 16); // -> 15

这是因为parseInt将继续逐行解析字符,直到它触及不知道的字符。 f*ck中的f是十六进制数字15

parseInt('Infinity', 10) // -> NaN
// ...
parseInt('Infinity', 18) // -> NaN...
parseInt('Infinity', 19) // -> 18
// ...
parseInt('Infinity', 23) // -> 18...
parseInt('Infinity', 24) // -> 151176378
// ...
parseInt('Infinity', 29) // -> 385849803
parseInt('Infinity', 30) // -> 13693557269
// ...
parseInt('Infinity', 34) // -> 28872273981
parseInt('Infinity', 35) // -> 1201203301724
parseInt('Infinity', 36) // -> 1461559270678...
parseInt('Infinity', 37) // -> NaN

在解析null时也要注意

parseInt(null, 24) // -> 23

它将null转换为字符串“null”,并尝试转换它。对于基数0到23,没有可以转换的数字,因此返回NaN。在24时,将第14个字母的“n”加到数字系统中。在31,添加第二十一个字母“u”,可以解码整个字符串。在37处,不再有可以生成的有效数字集合,并且返回NaN。

不要忘了八进制

parseInt('06'); // 6
parseInt('08'); // 8 ECMAScript 5
parseInt('08'); // 0 ECMAScript 3

这是因为,字符串从0开始,基数为8或10进制,parseInt()不加入第二个参数,es3中当作八进制处理,es5中当作十进制处理。所以,在使用parseInt()时,要指定基数。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容