JavaScript 运算中, 一共包含 4 个相等比较算法:
抽象相等比较
严格相等比较
- SameValueZero
- SameValue
可以这么说, 只要你做过相等比较, 你就在使用四个算法中的一个. 因为这些算法部署在了涉及到相等比较的操作符或方法中.
参见下表:
算法 使用了此算法的地方(部分) 抽象相等比较 == 运算符 严格相等比较 === 运算符, Array.prototype.indexOf 方法 SameValueZero String.prototype.includes,Array.prototype.includes 方法 SameValue Object.is 方法 怎样区分这些算法的不同呢, 可以从两方面切入:
是否会发生类型转换
对 NaN,-0,+0(即 0) 这些值是否存在特殊处理
下面给出一个总结:
发生类型转换? 特殊处理 NaN,-0,+0? 抽象相等比较 √ √ 严格相等比较 * √ SameValueZero * √ SameValue * * 就是说, 抽象相等比较算法会发生类型转换, SameValue 算法不会特殊对待 NaN,-0,+0 这些值.
类型转换如何进行的?
上面讨论的四种算法中, 只有 "抽象相等比较算法" 会发生类型转换. 发生类型转换的前提是: 比较的两个值类型不同, 而且转换结果是数值.
举个例子:
- 1 == 1 // true(未发生类型转换)
- '1' == 1 // true(发生了类型转换)
第一个比较为 true, 好理解; 第二个就不一样了, 会发生类型转换 -- 将非数字值转为数字:'1' 跟 1 比较, 两者类型不同,'1' 是字符串, 因此会先转为数字 -- 也就是 1(Number('1')), 结果变为两个 1 在一起比较, 结果就是 true 了.
"抽象相等比较算法" 还有一个比较怪癖的地方, 在于规范中定义 null == undefined 返回结果为 true. 按理说应该发生类型转换, 再进行比较的, 比较结果应为 false(null 转为 0,undefined 转为 NaN, 两者不等).
规范中对抽象相等比较算法搞了一个 "小怪癖": 定义 null 和 undefined 的比较结果为 true
我猜想, 这一定义可能是为了保证向前兼 (tián) 容(kēng), 因此, 我们记住即可. 除此之外的其他情况, 都按照类型转换后的比较结果为准.
NaN,-0 和 +0 是如何被特殊处理的?
ES2015 标准出版之前, 是没有 SameValueZero 和 SameValue 这两个算法的. 也就是说只有抽象相等比较和严格相等比较这两个算法: 这两个算法有点问题 -- 就是不能区分 NaN 以及 +0 和 -0. 因此在 ES2015 之前, 我们会遭遇这样的比较结果:
- NaN === NaN // false
- +0 === -0 // true
- [NaN].indexOf(NaN) // -1
[0].indexOf(-0) // -1
NaN 与自身不相等,+0 等于 -0. 在意识中, 我们可能接受不了 "NaN 与自身不相等" 的结果, 但是能够理解 "+0 等于 -0"(都是 0 嘛), 但是在某些符号位具有含义的场景中 --- 表示向左,+ 表示向右, 那么区分 +0 等于 -0 就有意义了.
基于此, ES2015 中引入了 SameValue 算法, Object.is() 方法内部就是使用此算法, 比较两个值是否相等.
- Object.is(NaN, NaN) // true
- Object.is(0, -0) // false
SameValueZero 算法, 通过名称我们可能就猜到, 与 SameValue 算法的区别, 仅仅是对 "零" 的态度上 --SameValueZero 算法不能区分 +0 和 -0.
就是说:
- var array = [NaN, -0]
- array.includes(NaN) // true
- array.includes(0) // true
array.includes(0) 的结果没有返回 false, 是因为其内部使用的 SameValueZero 算法不能区分 +0 和 -0.
参考链接
Equality comparisons and sameness, by MDN
我自己是一名从事了多年开发的 web 前端老程序员, 目前辞职在做自己的 Web 前端私人定制课程, 今年年初我花了一个月整理了一份最适合 2019 年学习的 Web 前端学习干货, 各种框架都有整理, 送给每一位前端小伙伴, 想要获取的可以添加我的 Web 前端交流群 600610151, 即可免费获取.
来源: http://www.jianshu.com/p/f7562261c8ed