专栏首页Fundebug怪异的JavaScript系列(一)

怪异的JavaScript系列(一)

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

本文采用意译,版权归原作者所有

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;

参考:

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。

参考:

NaN 不等于 NaN

NaN === NaN; // -> false

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

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

  1. 如果 x 是 NaN,那么返回 false;
  2. 如果 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

参考:

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 的规范。

参考:

最小值比 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

版权声明

转载时请注明作者 Fundebug以及本文地址: https://blog.fundebug.com/2018/04/03/javascript-werid-series-1/

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • WEB 实时推送技术的总结

    随着 Web 的发展,用户对于 Web 的实时推送要求也越来越高 ,比如,工业运行监控、Web 在线通讯、即时报价系统、在线游戏等,都需要将后台发生的变化主动地...

    Fundebug
  • 小程序框架对比 ( WePY / mpvue / Taro )

    众所周知如今市面上端的形态多种多样,手机 Web、ReactNative、微信小程序, 支付宝小程序, 快应用等,每一端都是巨大的流量入口,当业务要求同时在不同...

    Fundebug
  • 8个有意思的JavaScript面试题

    JavaScript 是一种有趣的语言,我们都喜欢它,因为它的性质。浏览器是JavaScript的主要运行的地方,两者在我们的服务中协同工作。JS有一些概念,人...

    Fundebug
  • hive中数据类型的转化CAST

    在《Hive内置数据类型》文章中,我们提到了Hive内置数据类型由基本数据类型和复杂数据类型组成。今天的话题是Hive数据类型之间的转换。同Java语言一样,H...

    学到老
  • 电商网站开发记录(二) mybatis三剑客的引入

    ,在resources下新建generatorConfig.xml,配置文件详细信息如下

    Dar_Alpha
  • hive中数据类型的转化CAST

    在《Hive内置数据类型》文章中,我们提到了Hive内置数据类型由基本数据类型和复杂数据类型组成。今天的话题是Hive数据类型之间的转换。同Java语言一样,H...

    学到老
  • kettle 利用 HTTP Client 获取猫眼电影API近期上映相关信息,并解析json

    Kettle 除了常规的数据处理之外,还可以模拟发送HTTP client/post ,REST client。

    YINUXY
  • CItrix StoreFront 3

    修改位于ASP.NET.CONFIG的文件:C:\Windows\Microsoft.NET\Framework64\v2.0.50727 和 C:\Windo...

    py3study
  • 小程序作为时代新产物崛起

    不管你想不想做,小程序都已是市场刚性需求。新时代产物的小程序有一套自己的打法,作为一种全新的连接用户与服务的方式,在中国被广大微信用户便捷地获取和传播,同时具有...

    虎超程序X
  • 分析Oracle数据库日志文件(1)

    分析Oracle数据库日志文件(1) 一、如何分析即LogMiner解释 从目前来看,分析Oracle日志的唯一方法就是使用Oracle公司提供的LogMin...

    阿新

扫码关注云+社区

领取腾讯云代金券