前言
当我们想在JavaScript中比较两个值时, 第一时间想到的就是相等运算符(==)或全等运算符(===),由于相等运算符在比较时可能会触发存在强制类型转换,我们更喜欢后者。但是全等运算符也不完全准确,比如,+0和-0在JavaScript引擎中被表示为两个完全不同的实体,但是如果用全等运算符(===)来比较,得到的结果是两者相等了,又如,NaN===NaN的返回结果是false。
为此,ES6引入了Object.is()方法来弥补全等运算符的不准确运算,下面我们来介绍一下这个API的用法和功能
语法
Object.is(value1, value2);
参数说明
value1
:第一个需要比较的值。
value2
:第二个需要比较的值。返回值:表示两个参数是否相同的布尔值
执行机制
Object.is() 判断两个值是否相同。如果下列任何一项成立,则两个值相同:
- 两个值都是 undefined
- 两个值都是 null
- 两个值都是 true 或者都是 false
- 两个值是由相同个数的字符按照相同的顺序组成的字符串
- 两个值指向同一个对象
- 两个值都是数字并且
- 都是正零 +0
- 都是负零 -0
- 都是 NaN
- 都是除零和 NaN 外的其它同一个数字
这种相等性判断逻辑和传统的相等运算符 (==) 运算不同,== 运算符会对它两边的操作数做隐式类型转换(如果它们类型不同),然后才进行相等性比较,(所以才会有类似 "" == false 等于 true 的现象),但 Object.is 不会做这种类型转换。
但是需要注意的是,== 运算符对操作数进行隐式类型转换也是有“规律”的,比如,null转换为Number类型是0,但是0==null 的返回值是false。这种“规律”与JavaScript的内部有关,想要彻底理解就要去读JavaScript的规格了,而对于相等运算符(==)的运算,它的规格翻译如下:
假定判断 x==y ,
- 如果
x
不是正常值(比如抛出一个错误),中断执行。- 如果
y
不是正常值,中断执行。- 如果
Type(x)
与Type(y)
相同,执行严格相等运算x === y
。- 如果
x
是null
,y
是undefined
,返回true
。- 如果
x
是undefined
,y
是null
,返回true
。- 如果
Type(x)
是数值,Type(y)
是字符串,返回x == ToNumber(y)
的结果。- 如果
Type(x)
是字符串,Type(y)
是数值,返回ToNumber(x) == y
的结果。- 如果
Type(x)
是布尔值,返回ToNumber(x) == y
的结果。- 如果
Type(y)
是布尔值,返回x == ToNumber(y)
的结果。- 如果
Type(x)
是字符串或数值或Symbol
值,Type(y)
是对象,返回x == ToPrimitive(y)
的结果。- 如果
Type(x)
是对象,Type(y)
是字符串或数值或Symbol
值,返回ToPrimitive(x) == y
的结果。- 返回
false
。
知道了这些再看 0 == null 返回 false 就很明白了:
由于0
的类型是数值,null
的类型是 Null(注意:这是规格4.3.13 小节的规定,是内部 Type 运算的结果,跟typeof
运算符无关)。因此上面的前 11 步都得不到结果,要到第 12 步才能得到结果,结果为false
。
当然这是补充的知识,现在我们再回过头来看Object.is()
Object.is()这种相等性判断逻辑与 ===运算符的判定方式也不一样。===运算符(和 == 运算符)将数字值 -0 和 +0 视为相等,并认为Number.NaN不等于 NaN。
实例演示
Object.is('foo', 'foo'); // true 两个相同字符串
Object.is('1',1) // false 不会自动转换
Object.is('foo', 'bar'); // false
Object.is([], []); // false
Object.is(null, null); // true
Object.is(window, window); // true 相同对象
var foo = { a: 1 };
var bar = { a: 1 };
Object.is(foo, foo); // true
Object.is(foo, bar); // false 不同对
// 特例
Object.is(0, -0); // false
Object.is(0, +0); // true
Object.is(-0, -0); // true
Object.is(NaN, 0/0); // true