网站首页 > 技术文章 正文
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前端学习干货,各种框架都有整理,送给每一位前端小伙伴,想要获取的可以关注我的头条号并在后台私信我:前端,即可免费获取。
作者:zhangbao90s
链接:https://juejin.im/post/5dbbd439f265da4d4434a976
猜你喜欢
- 2024-11-23 「实战」用原生的 Intersection Observer API 实现 Lazy Loading
- 2024-11-23 JS:缓存数据用哪个?Storage有什么区别?
- 2024-11-23 如何在页面关闭或跳转时优雅的发送Ajax请求
- 2024-11-23 API 终结者——杀手 Reflect
- 2024-11-23 大救星:延展操作符,是如何运作的?
- 2024-11-23 vue3.0项目开发(三)新特性之响应式系统reactive函数
- 2024-11-23 自动驾驶规模落地,不能被激光雷达卡脖子
- 2024-11-23 JavaScript 有趣的冷知识:标签模板(tagged template)
- 标签列表
-
- content-disposition (47)
- nth-child (56)
- math.pow (44)
- 原型和原型链 (63)
- canvas mdn (36)
- css @media (49)
- promise mdn (39)
- readasdataurl (52)
- if-modified-since (49)
- css ::after (50)
- border-image-slice (40)
- flex mdn (37)
- .join (41)
- function.apply (60)
- input type number (64)
- weakmap (62)
- js arguments (45)
- js delete方法 (61)
- blob type (44)
- math.max.apply (51)
- js (44)
- firefox 3 (47)
- cssbox-sizing (52)
- js删除 (49)
- js for continue (56)
- 最新留言
-