ES2015中有四种相等算法:
- 抽象(非严格)相等比较 (
==) - 严格相等比较 (
===): 用于Array.prototype.indexOf,Array.prototype.lastIndexOf, 和case-matching - 同值零: 用于
%TypedArray%和ArrayBuffer构造函数、以及Map和Set操作, 并将用于 ES2016/ES7 中的String.prototype.includes - 同值: 用于所有其他地方
JavaScript提供三种不同的值比较操作:
- 严格相等比较 (也被称作"strict equality", "identity", "triple equals"),使用 === ,
- 抽象相等比较 ("loose equality","double equals") ,使用 ==
- 以及
Object.is(ECMAScript 2015/ ES6 新特性)
理解相等比较的模型
什么时候使用 Object.is 或是三等
总的来说,除了对待NaN的方式,Object.is唯一让人感兴趣的,是当你需要一些元编程方案时,它对待0的特殊方式,特别是关于属性描述器,即你的工作需要去镜像Object.defineProperty的一些特性时。如果你的工作不需要这些,那你应该避免使用Object.is,使用===来代替。即使你需要比较两个NaN使其结果为true,总的来说编写使用NaN 检查的特例函数(用旧版本ECMAScript的isNaN方法)也会比想出一些计算方法让Object.is不影响不同符号的0的比较更容易些。
这里是一个会区别对待-0和+0的内置方法和操作符不完全列表:
-
显而易见,对
0一元负操作得到``-0。但表达式的抽象化可能在你没有意识到得情况下导致-0延续传播。例如当考虑下例时:let stoppingForce = obj.mass * -obj.velocityCopy to Clipboard
如果
obj.velocity是0(或计算结果为0),一个-0就在上处产生并被赋值为stoppingForce的值. -
Math.atan2,Math.ceil,Math.pow,Math.round即使传入的参数中没有-0,这些方法的返回值都有可能是-0。例如当用
Math.pow计算-Infinity的任何负奇指数的幂都会得到-0。详情请参见这些方法各自的文档。 -
Math.floor,Math.max,Math.min,Math.sin,Math.sqrt,Math.tan当传入参数中有-0时,这些方法也可能返回-0。例如,
Math.min(-0, +0)得出-0。详情请参见这些方法各自的文档。 -
这些操作符内部都使用了ToInt32算法。因为内部32位整数类型只有一个0(没有符号区别),-0的符号在反操作后并不会保留下来。例如
Object.is(~~(-0), -0)和Object.is(-0 << 2 >> 2, -0)都会得到false.
在未考虑0的符号的情况下依赖于Object.is是危险的。当然,如果本意就是区分-0和+0的话,Object.is能按照期望完成工作。
文章来源: MDN-JavaScript 中的相等性判断