Javascript相等性判断

105 阅读4分钟

众所周知,javascript是类型不严格的语言,因此在相等判断时,可能会出现因类型转换,以及不同比较规则导致的混淆。此处整理以记忆不同相等性判断方法基本数据类型上的区别

相等性判断概览

Javascipt提供的常用相等判断api

==,===,Object.is

相等性判断抽象概念

  • IsLooselyEqual:==
  • IsStrictlyEqual:===
  • SameValue同值相等:Object.is()
  • SameValueZero零值相等:被许多内置运算(涉及相等性判断处)使用

相等性判断方式分析

"=="

会进行隐式类型转换

但要注意的是 undefined 和 null 参与运算时不会类型转换

所以null、undefined和其他比较都返回false

但是undefined == null返回true

"==="

严格相等

但要注意NaN === NaN返回false

因此:

数组索引查找方法也使用严格相等,包括 Array.prototype.indexOf()、Array.prototype.lastIndexOf()、TypedArray.prototype.index()、TypedArray.prototype.lastIndexOf() 和 case 匹配。这意味着你不能使用 indexOf(NaN) 查找数组中 NaN 值的索引,也不能将 NaN 用作 case 值在 switch 语句中匹配任何内容。

"Object.is"(同值相等

同值相等的人柱力,同值相等决定了两个值在所有上下文中是否在功能上相同

可以用里氏替换原则的思路来理解

// 向 Nmuber 构造函数添加一个不可变的属性 NEGATIVE_ZERO
Object.defineProperty(Number, "NEGATIVE_ZERO", {
  value: -0,
  writable: false,
  configurable: false,
  enumerable: false,
});

// 调用以下函数会使用Object.is来比较变动
// attemptMutation(0)会弹出错误
function attemptMutation(v) {
  Object.defineProperty(Number, "NEGATIVE_ZERO", { value: v });
}

1.对于+0 -0在不同上下文中的区别

  • Number.parseInt("-0")会返回-0。
  • 1/-0为-Infinity,而1/+0为+Infinity。
  • 在JSON.stringify()中+0会输出为0,但-0会输出为-0。
  • canvas渲染时+0和-0的颜色可能不同。
  • +0内部是以一串二进制数"0x0000000000000"的形式存储;而-0内部是"0x8000000000000"

可能因此认为正负零不同值

2.对于NaN

Number.NaN,Object.is认为NaN的值都是相同的全局对象属性,因此认为其是同值

零值相等

基于同值相等,零值变为相等

零值相等与严格相等的区别在于其将 NaN 视作是相等的,与同值相等的区别在于其将 -0 和 0 视作相等的。这使得它在搜索期间通常具有最实用的行为,特别是在与 NaN 一起使用时。它被用于 Array.prototype.includes()、TypedArray.prototype.includes() 及 Map 和 Set 方法用来比较键的相等性。

区别和联系

==和===代码中最常见的相等判断,区分在于会不会做隐式转换

Object.is和同值相等Object.is是实现同值相等的方法,同值相等的载体是Object.is

同值相等和零值相等是一对区别的概念

记忆法

首先记住特殊的null == undefined 结果为 true

然后记住类型转换的方法和引用类型的判断

之后特殊的区别集中在

xy===Object.isSameValueZero
+0-0✅ true❌ false✅ true
0-0✅ true❌ false✅ true
NaNNaN❌ false✅ true✅ true

Object.is,也即同值相等是最原始的比较方式,因此在NaN和+-0的比较上不做特殊处理

===是特化数字比较的Object.is,处理了遇到NaN和+-零的情况,使其符合相等比较的使用习惯,NaN因包含了不确定的非数被认为是不相等的,+-0在相等比较的语境下不需要做区别

==是特化类型转换的===

零值相等是特化搜索的同值相等,在搜索中,我们关注的重点不在0的+-上,因此两者相等

比较结果的对比

运用刚刚的知识来验证一下这个表格吧!

xy=====Object.isSameValueZero
undefinedundefined✅ true✅ true✅ true✅ true
nullnull✅ true✅ true✅ true✅ true
truetrue✅ true✅ true✅ true✅ true
falsefalse✅ true✅ true✅ true✅ true
'foo''foo'✅ true✅ true✅ true✅ true
00✅ true✅ true✅ true✅ true
+0-0✅ true✅ true❌ false✅ true
+00✅ true✅ true✅ true✅ true
-00✅ true✅ true❌ false✅ true
0n-0n✅ true✅ true✅ true✅ true
0false✅ true❌ false❌ false❌ false
""false✅ true❌ false❌ false❌ false
""0✅ true❌ false❌ false❌ false
'0'0✅ true❌ false❌ false❌ false
'17'17✅ true❌ false❌ false❌ false
[1, 2]'1,2'✅ true❌ false❌ false❌ false
new String('foo')'foo'✅ true❌ false❌ false❌ false
nullundefined✅ true❌ false❌ false❌ false
nullfalse❌ false❌ false❌ false❌ false
undefinedfalse❌ false❌ false❌ false❌ false
{ foo: 'bar' }{ foo: 'bar' }❌ false❌ false❌ false❌ false
new String('foo')new String('foo')❌ false❌ false❌ false❌ false
0null❌ false❌ false❌ false❌ false
0NaN❌ false❌ false❌ false❌ false
'foo'NaN❌ false❌ false❌ false❌ false
NaNNaN❌ false❌ false✅ true✅ true

参考:MDN-相等性判断