[译] 我见过最好最详细的 JavaScript 关系的解释

TLDR:强迫自己使用三重等号(===)

我无意在Reddit上找到了这个JavaScript meme,它是我见过最好的抽象。

你可以通过运行开发者工具来运行(图中)的每行代码来验证此关系的准确性。结果并不令人惊讶,但仍然令人失望。

当然,这个小实验触发了我的兴趣...

这是怎么发生的?

凭借经验,我学会了接受JavaScript这滑稽的一面,同时感受它的松散。尽管如此,这个事件的细节仍然让我感到困惑。

正如Kyle Simpson所说...

"不管怎么说,我认为任何人都不会真正了解JS"

当这些案例出现时,最好查阅源代码--构建JavaScript的官方ECMAScript规范

有了这个规范,让我们深刻理解这里发生了什么。

板块1 - 引入强制

如果你在开发者控制台上运行0 == "0",为什么它返回true

0是一个数字,然后"0"是一个字符串,它们永远不应该相同的!大多数编程语言都遵守它。例如,Java中的0 == "0",会返回下面这个:

error: incomparable types: int and String

这很有道理。如果要比较Java中的intString,必须先把它们转换为相同的类型。

但这是JavaScript,你们呀!

当你通过==比较两个值时,其中一个值可能受到强制转换。

强制 - 自动将值从一种类型转换为另一种类型。

这里的自动是关键词。JavaScript不是在显式转换你的类型,而是在幕后帮你完成。

如果你有目的地利用它,这很方便,但如果你不知道它的含义,则可能有害。

这是关于它的官方ECMAScript语言规范。 我会解释相关部分:

If x is Number and y is String, return x == ToNumber(y)

译:如果 x 是数字类型,y 是字符串类型,将 y 转换成数字类型与 x 作比较后返回

所以我们的例子0 == "0"

因为 0 是一个数字类型,"0" 是一个字符串类型,则返回 0 == ToNumber("0")

我们的字符串"0"已经被秘密转换成数字0,现在我们有一个匹配了!

0 == "0" // true
// The second 0 became a number!
// so 0 equals 0 is true....

奇怪吧?好好习惯它,我们接着说~

板块2 - 数组也被强制

这种强制不仅仅限制于字符串,数字或布尔值等基本数据类型。这是我们的下一个比较:

0 == [] // true
// What happened...?

再次被强制了!我将解释规范的相关部分:

If x is String or Number and y is Object, return x == ToPrimitive(y)

译:如果 x 是字符串或数字类型,然后 y 是对象类型,将 y 转换为基本数据类型与 x 作比较后返回

这里有三件事:

1.是的,数组是对象

抱歉,刷新了你的认知。

2.空数组变成空字符串

再次根据规范,JS首先寻找一个对象的toString方法来强制转换它。

在数组的情况下,toString连接其所有元素并将它们作为字符串返回。

[1, 2, 3].toString() // "1,2,3"
['hello', 'world'].toString() // "hello,world"

因为我们的数组是空的,我们没内容去拼接!所以...

[].toString() // ""

规范中的ToPrimitive将空数组转换成空字符串。相关的参考在这里这里,方便你查阅(或解决疑惑)。

3.空字符串然后变成0

你不能把这些东西搞定。现在我们已经将数组强制变成"",我们又回到了第一个算法(规范)...

If x is Number and y is String, return x == ToNumber(y)

所以0==""

Since 0 is Number and "" is String, return 0 == ToNumber("")

ToNumber("")返回 0 。

因此,再一次是0==0...

板块3 - 快速回顾

这是正确的

0 == "0" // true

因为被强制转换成这个0 == ToNumber("0")

这也是正确的

0 == [] // true

因为强制转换执行两次:

  1. ToPrimitive([])转换为空字符串
  2. 然后ToNumber("")转换为 0 。

所以,告诉我...根据上面的规则,下面将返回什么?

"0" == []

板块4 - FALSE!

FALSE! 正确。

如果你明白规则,这部分是有意义的。

下面是我们的比较:

"0" == [] // false

再次参考规范:

If x is String or Number and y is Object, return x == ToPrimitive(y)

那就意味着...

Since "0" is String and [] is Object, return x == ToPrimitive([])

"0" == ""

"0"""都是字符串类型,所以JavaScript不需要再强制转换了。这就是为什么得到结果为false的原因。

总结

使用三重等号(===),然后晚上睡个好觉。

0 === "0" // false
0 === [] // false
"0" === [] // false

它完全避免强制转换,所以我猜它也更有效率!

但是('==='对于)性能的提升几乎毫无意义。真正的胜利是你在代码中增加的信心,使得额外的击打键盘完全值得。

参考和后话

更多的内容,请戳我的博客进行了解,能留个star就更好了?

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Eureka伽罗的技术时光轴

android中webview控件和javascript交互实例

当我们要实现丰富的图文混排效果的时候,我们一般会使用webview,这是一个功能十分强大的的控件,来看看官方的解释:

13120
来自专栏Eureka伽罗的技术时光轴

Delphi xe10对json的解析应用

{"code":100,"state":"true","data":["hero","npc","pet"]}

19120
来自专栏Jerry的SAP技术分享

how do you usually upload picture in SCN A workaround for current SCN upload is

版权声明:署名,允许他人基于本文进行创作,且必须基于与原先许可协议相同的许可协议分发本文 (Creative Commons)

12040
来自专栏Java系列文章

如何排查Java内存泄漏?看完我给跪了!

没有经验的程序员经常认为Java的自动垃圾回收完全使他们免于担心内存管理。这是一个常见的误解:虽然垃圾收集器做得很好,但即使是最好的程序员也完全有可能成为严重...

10420
来自专栏编程坑太多

『互联网架构』kafka前世今生和安装部署(116)

12030
来自专栏python-爬虫

BeautifulSoup库整理

注意:如果是html的父标签就是他自己,soup本身也是种特殊的标签的他的父标签是空

6620
来自专栏即时通讯技术

自已开发IM有那么难吗?手把手教你自撸一个Andriod版简易IM (有源码)

一直想写一篇关于im即时通讯分享的文章,无奈工作太忙,很难抽出时间。今天终于从公司离职了,打算好好休息几天再重新找工作,趁时间空闲,决定静下心来写一篇文章,毕竟...

22620
来自专栏python-爬虫

迭代器,三元表达式,列表生成式,字典生成式,生成器,递归(没深入理解)

yield的英文单词意思是生产,在函数中但凡出现yield关键字,再调用函数,就不会继续执行函数体代码,而是会返回一个值

7210
来自专栏Eureka伽罗的技术时光轴

android--WebView使用addJavascriptInterface在sdk 17的问题

当调用WebView 的addJavascriptInterface时,使用android:targetSdkVersion="10"时是没有问题的,能够触发事...

9220
来自专栏python-爬虫

力扣题目汇总(位1的个数,有效的字母异位词,检测大写字母)

否则,我们定义这个单词没有正确使用大写字母。 示例 1: 输入: "USA" 输出: True 示例 2: 输入: "FlaG" 输出: False ...

8220

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励