JavaScript中有四种相等性的判断算法:
==
宽松相等===
严格相等- 同值相等
(-0 !== +0) NaN === NaN
- 零值相等
(-0 === +0)
JavaScript中相等性判断的方法:
===
严格相等(strict equality)
==
非严格相等(抽象/非约束)相等(loose equality)
Object.is(v1, v2)
严格相等
- 不进行隐式类型转换,若比较的两个操作数类型相同,值也相同,则结果为
true
1 === '1' ? false
1 === 2 ? false
- 引用值为同一地址,结果为
true
var obj = {}
obj === obj ? true
{} === {} ? false
NaN
和任何值都不相等,包括它本身
NaN === NaN ? false
NaN === undefined ? false
+0
和-0
相等+Infinity
和-Infinity
不相等
延伸:如何定义一个变量a,使得a !== a的结果为true?答:将a设为NaN。
非严格相等
- 两个操作数在进行非严格相等判断之前会先进行隐式类型转换,转换以后还是用严格相等
===
来进行比较,具体比较规则如下:
ToPrimitive(A)通过尝试调用 A 的A.toString() 和 A.valueOf() 方法,将参数 A 转换为原始值(Primitive)
- 任何对象都与
undefined
和null
不相等
({}) == undefined ? false
({}) == null ? false
同值相等(same-value)
- 同值相等中会认为
+0 !== -0
,可利用Object.defineProperty()
验证,例如
var obj = {}
// 给obj定义一个属性a
Object.defineProperty(obj, 'a', {
value: -0,
writable: false,
configurable: false,
enumerable: false
})
// 再对obj对象操作a属性,因为a是不可变属性,所以如果设置的值不同,会报错
Object.defineProperty(obj, 'a', {
value: +0, // 报错
writable: false,
configurable: false,
enumerable: false
})
- 同值相等中认为
NaN === NaN
,同样可利用Object.defineProperty()
验证:
var obj = {}
// 给obj定义一个属性a
Object.defineProperty(obj, 'a', {
value: NaN,
writable: false,
configurable: false,
enumerable: false
})
Object.defineProperty(obj, 'a', {
value: NaN, // 不报错
writable: false,
configurable: false,
enumerable: false
})
- 同值比较底层实现使用的是
Object.is()
方法,只是ES6把这个方法暴露了出来 - 手写
Object.is()
的实现
function myObjectIs(a, b) {
/*
判断如果a===b为true,需要分两种情况:
两者都不为0,则在判断a !== -0 结果直接返回true
两者为0,如果一个为-0,一个为+0,则1/-0 === -Infinity,1/+0 === +Infinity,1/-0 === 1/+0 结果返回false
*/
if(a === b) {
return a !== -0 || (1/a === 1/b)
}
/*
若两者不相等,分两种情况:
两者都不为NaN,则a !== a && b !== b返回false
两者都为NaN,则a !== a && b !== b返回true
*/
return a !== a && b !== b
}
零值相等
- 零值相等与同值相等一样,但是会认为
-0 === +0
结果为true
===
判断和Object.is()
判断的区别在对-0
和+0
、NaN
和NaN
判断的结果不一样。