侧边栏壁纸
博主头像
woku博主等级

成功的路上并不拥挤

  • 累计撰写 50 篇文章
  • 累计创建 13 个标签
  • 累计收到 3 条评论

相等性判断与Object.is

woku
2021-11-22 / 0 评论 / 0 点赞 / 47 阅读 / 2,436 字

ES6版本中,有4种相等判断的算法

  • 全等 ===

  • 等于 ==

  • 同值相等 +0 !== -0 NaN === NaN

  • 零值相等 +0 === -0

JS中提供3种相等判断的操作方法

  • 严格相等

  • 非严格相等

  • Object.is

严格相等(===)

strict equality

使用严格相等是不进行类型转换的,必须值和类型都相等

引用值必须是同一个地址

var num = 0;
var obj = new String("0");
var str = "0";
var b = false;

console.log(num === num); // true
console.log(obj === obj); // true
console.log(str === str); // true

console.log(num === obj); // false
console.log(num === str); // false
console.log(obj === str); // false
console.log(null === undefined); // false
console.log(obj === null); // false
console.log(obj === undefined); // false

在严格相等中,+0 === -0

NaN !== NaN

console.log(+0 === -0)  // true
console.log(NaN === NaN)  // false

等式 (x !== x) 成立的唯一情况是 x 的值为 NaN

非严格相等(==)

等式两边的值有可能进行隐士类型转换

转换完后,再用全等操作符===进行比较

   console.log(1 == '1')   // true
   console.log(null == undefined)   // true

相等操作符对于不同类型的值,进行的比较如下图所示:

被比较值 B
UndefinedNullNumberStringBooleanObject
被比较值 AUndefinedtruetruefalsefalsefalseIsFalsy(B)
NulltruetruefalsefalsefalseIsFalsy(B)
NumberfalsefalseA === BA === ToNumber(B)A=== ToNumber(B)A== ToPrimitive(B)
StringfalsefalseToNumber(A) === BA === BToNumber(A) === ToNumber(B)ToPrimitive(B) == A
BooleanfalsefalseToNumber(A) === BToNumber(A) === ToNumber(B)A === BToNumber(A) == ToPrimitive(B)
ObjectfalsefalseToPrimitive(A) == BToPrimitive(A) == BToPrimitive(A) == ToNumber(B)A === B

ToNumber(A) 尝试在比较前将参数 A 转换为数字

ToPrimitive(A)通过尝试调用 A 的A.toString() 和 A.valueOf() 方法,将参数 A 转换为原始值(Primitive)

一般而言,根据 ECMAScript 规范,所有的对象都与 undefined 和 null 不相等。但是大部分浏览器允许非常窄的一类对象(即,所有页面中的 document.all 对象),在某些情况下,充当效仿 undefined 的角色。相等操作符就是在这样的一个背景下。因此,IsFalsy(A) 方法的值为 true ,当且仅当 A 效仿 undefined。在其他所有情况下,一个对象都不会等于 undefined 或 null

(此段知识点摘自MDN)

同值相等

same-value

+0和-0

   var obj = {}
   Object.defineProperty(obj,'a',{
     value:+0,
     writable: false,
     configurable:false,
     enumerable:false
   })
   Object.defineProperties(obj,'a',{
     value: -0
   })

运行上面的代码,在定义属性a时设置了不可重写

报错说明

在使用Object.defineProperty定义属性的时候,他认为+0 !== -0

NaN和NaN

   var obj = {}
   Object.defineProperty(obj,'a',{
     value:NaN,
     writable: false,
     configurable:false,
     enumerable:false
   })
   Object.defineProperty(obj,'a',{
     value: NaN
   })

运行上面的代码,不会报错,

说明NaN === NaN

零值相等

same-value-zero

+0 === -0

Object.is

ES6中抛出来的方法

同值相等的实现

和 严格相等===的不同之处在于

+0 !== -0

NaN === NaN

   console.log(Object.is({},{}))          // false
   console.log(Object.is(1,1))            // true
   console.log(Object.is(1,'1'))          // false
   console.log(Object.is(undefined,null)) // false
   console.log(Object.is(+0,-0))          // false
   console.log(Object.is(NaN,NaN))        // true

实现Object.is

Object.myIs = function(a,b) {
  if(a === b) {
    return a !== 0 || ( 1 / a === 1 / b)
  }
  return a !== a && b !== b
}

:::tip

1 / +0 Infinity

1 / -0 -Infinity

a !== a 只有当a是NaN的时候满足

:::

什么时候用严格相等,什么时候用非严格相等

准确判断类型和值的时候用严格相等

开发插件,用户传入的参数之类的可以用非严格相等,这样不用限制用户在使用插件的时候必须同等类型的参数

0

评论区