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

banner

TLDR:强迫本身使用三重等号(===)

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

tldr

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

固然,这个小实验触发了个人兴趣...git

这是怎么发生的?

why-does-this-happen

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

正如Kyle Simpson所说...算法

"无论怎么说,我认为任何人都不会真正了解JS"编程

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

有了这个规范,让咱们深入理解这里发生了什么。app

板块1 - 引入强制

panel-1-1

若是你在开发者控制台上运行0 == "0",为何它返回true编程语言

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

error: incomparable types: int and String
复制代码

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

但这是JavaScript,大家呀!

this-is-javascript

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

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

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

scumbag-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....
复制代码

that-string-secretly-became-a-number

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

板块2 - 数组也被强制

panel-2

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

0 == [] // true
// What happened...?
复制代码

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

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

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

这里有三件事:

1.是的,数组是对象

arrays-are-objects

抱歉,刷新了你的认知。

2.空数组变成空字符串

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

在数组的状况下,toString链接其全部元素并将它们做为字符串返回。

[1, 2, 3].toString() // "1,2,3"
['hello', 'world'].toString() // "hello,world"
复制代码

由于咱们的数组是空的,咱们没内容去拼接!因此...

[].toString() // ""
复制代码

empty-array-coerces-to-empty-string-1

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

3.空字符串而后变成0

empty-strings-become-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...

coercion-every-time-2

板块3 - 快速回顾

panel-3-1

这是正确的

0 == "0" // true
复制代码

由于被强制转换成这个0 == ToNumber("0")

这也是正确的

0 == [] // true
复制代码

由于强制转换执行两次:

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

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

"0" == []
复制代码

板块4 - FALSE!

panel-4-1

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的缘由。

总结

just-use-triple-equals

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

0 === "0" // false
0 === [] // false
"0" === [] // false
复制代码

它彻底避免强制转换,因此我猜它也更有效率!

可是('==='对于)性能的提高几乎毫无心义。真正的胜利是你在代码中增长的信心,使得额外的击打键盘彻底值得。

参考和后话

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

相关文章
相关标签/搜索