资讯专栏INFORMATION COLUMN

怪异的JavaScript系列(一)

darry / 2108人阅读

摘要:是一门伟大的语言,它拥有非常简洁的语法,庞大的生态系统,以及最重要的有一个伟大的社区支撑着。可是因为它已经被广泛使用,所以委员会觉得保留它,但是违背了的规范。其实最小的数是,尽管它不是一个实际存在的数。

译者按: JavaScript有很多坑,经常一不小心就要写bug。

原文: What the f*ck JavaScript?

译者: Fundebug

为了保证可读性,本文采用意译而非直译。另外,本文版权归原作者所有,翻译仅用于学习。

JavaScript是一门伟大的语言,它拥有非常简洁的语法,庞大的生态系统,以及最重要的:有一个伟大的社区支撑着。同时,我们也知道JavaScript是一个充满技巧性的语言。有些坑足以让我们崩溃,也有些奇淫技巧让我们觉得很有趣。本文的思想源自于Brian Leroux在dotJS2012上的演讲“WTFJS” at dotJS 2012。



我收集这些例子的主要目的是将它们整理并清楚理解它们的原理。从中学到很多以前不懂的知识是一件很有趣的事情。如果你是初学者,你可以通过学习这些笔记深入理解JavaScript;如果你是一个专业的开发者,那么可以将这些笔记作为一个不错的引用资料。不管怎样,只要读下去,你就会学到新东西的。

[]等于![]
[ ] == ![ ] // -> true

相等(==)判断操作会将两边的类型都转换为数字(number),然后再比较。因为[]![]都会转换为0。我们可以理解[]是一个数组,只不过为空而已,那么为true。右侧![]则为false。false然后转换为数字0。左侧[]直接转换为数字,因为空数组会转换为0,所以尽管我们认为[]为true,这里却变成了0

下面是简化的计算过程:

+[] == +![]
0 == +false
0 == 0
true

参考:

12.5.9 Logical NOT Operator (!)

7.2.13 Abstract Equality Comparison

true 是 false
!!"false" ==  !!"true"  // -> true
!!"false" === !!"true" // -> true

true是一个真值,用1表示;字符串的“true”则为NaN。

true == "true"    // -> false
false == "false"  // -> false

"false"是一个有意义的字符串。

!!"false" // -> true
!!"true"  // -> true

参考:7.2.13 Abstract Equality Comparison

baNaNa
"b" + "a" + + "a" + "a" // -> baNaNa

这是一个旧笑话,不过改进过的。原始的长这样:

"foo" + + "bar" // -> "fooNaN"

该表达式以"foo" + (+"bar")的形式计算,因为bar不是数字,所以转换为NaN。

参考:

12.8.3 The Addition Operator (+)

12.5.6 Unary + Operator

NaN不等于NaN
NaN === NaN // -> false

根据===的算法,我们可以容易理解为什么为false。

如果typeof(x)和typeof(y)不同,那么返回false.
否则,如果typeof(x)是Number,那么

如果x是NaN,那么返回false;

如果y是NaN,那么返回false;

...

由此可以得出值为false的结论。

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

如果我们仔细观察序列的规律,会发现下面的模式出现很多次:

(![]+[]) // -> "false"
![]      // -> false

因此,我们尝试将[]和false相加。但是根据内部一些列函数的计算(binary + Operator -> ToPrimitive -> [[DefaultValue]]),右侧的[]最终转换为string:

(![]+[].toString()) // "false"

对于一个字符串,我们就可以通过下标来获取对应的字符:

"false"[0] // -> "f"

剩下的都很直观,除了i很取巧。fail中的i是通过在falseundefined中获取第十个下标对应的字符而得到。

[]包含值,但不是true

空数组不等于true。(An array is a truthy value, however, it"s not equal to true.)

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

参考:

12.5.9 Logical NOT Operator (!)

7.2.13 Abstract Equality Comparison

null不等于false

尽管null是一个false的值,但是null不等于false。

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

不过,如果和其它false的值比较,那么他们又是相等的。

0 == false  // -> true
"" == false // -> true

参考: 7.2.13 Abstract Equality Comparison

JavaScript坑很多,赶紧使用fundebug扶一扶!

document.all是一个对象,不过是undefined

⚠️这个是前端浏览器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的规范。

参考:

Obsolete features - document.all

Chapter 4 - ToBoolean - Falsy values

最小值比0还大

Number.MIN_VALUE是最小的数,但是它比0还大。

Number.MIN_VALUE > 0 // -> true

因为Number.MIN_VALUE5e-324。也就是说即使最小的值也可以用浮点数表示出来,虽然离0很接近,但是依然比0大。其实最小的数是Number.NEGATIVE_INFINITY,尽管它不是一个实际存在的数。

在StackOverflow有相关问题:Why is 0 less than Number.MIN_VALUE in JavaScript?。

参考: 20.1.2.9 Number.MIN_VALUE

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/94549.html

相关文章

  • 怪异JavaScript系列(三)

    摘要:本文的思想源自于在上的演讲。我收集这些例子的主要目的是将它们整理并清楚理解它们的原理。着主要是因为大括号也是函数定义语法的一部分。自从年双十一正式上线,累计处理了亿错误事件,得到了金山软件等众多知名用户的认可。 译者按: JavaScript有很多坑,经常一不小心就要写bug。 原文: What the f*ck JavaScript? 译者: Fundebug 为了保证可读性...

    XboxYan 评论0 收藏0
  • 怪异JavaScript系列(二)

    摘要:函数不是函数这是一个低版本的,,或则。对应的进制数为。因此最安全的方法是调用的时候指定进制。它会将字符串形式的整数转换为,非字符串的,,和也会被转换。对于不能转换的值,返回。而浏览器主要指系列,其实已经没有必要支持这个特性了。 译者按: JavaScript有很多坑,经常一不小心就要写bug。 原文: What the f*ck JavaScript? 译者: Fundebug ...

    YacaToy 评论0 收藏0
  • 前端知识点总结

    摘要:知识点一和浏览器渲染模式文档类型,一个文档类型标记是一种标准通用标记语言的文档类型声明,它的目的是要告诉标准通用标记语言解析器,它应该使用什么样的文档类型定义来解析文档。知识点二文件类型声明仅有一型。知识点三常用整理常用整理 知识点一:DOCTYPE和浏览器渲染模式 文档类型,一个文档类型标记是一种标准通用标记语言的文档类型声明,它的目的是要告诉标准通用标记语言解析器,它应该使用什么样...

    AprilJ 评论0 收藏0
  • 前端知识点总结

    摘要:知识点一和浏览器渲染模式文档类型,一个文档类型标记是一种标准通用标记语言的文档类型声明,它的目的是要告诉标准通用标记语言解析器,它应该使用什么样的文档类型定义来解析文档。知识点二文件类型声明仅有一型。知识点三常用整理常用整理 知识点一:DOCTYPE和浏览器渲染模式 文档类型,一个文档类型标记是一种标准通用标记语言的文档类型声明,它的目的是要告诉标准通用标记语言解析器,它应该使用什么样...

    TNFE 评论0 收藏0

发表评论

0条评论

darry

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<