JavaScript如何正确的判断两个值相等

280 阅读3分钟

「这是我参与2022首次更文挑战的第9天,活动详情查看:2022首次更文挑战」。

JavaScript中提供了三种不同的值比较操作:

  1. 抽象相等比较:使用==
  2. 严格相等比较:使用===
  3. ES6新特性:Object.is

严格相等 ===

全等操作符比较两个值是否相等,两个被比较的值在比较前都不进行隐式转换。如果两个被比较的值具有不同的类型,会返回false。否则,如果两个被比较的值类型相同,值也相同,并且都不是 number 类型时,两个值全等。

如果两个值都是 number 类型,当两个值都不是 NaN,并且数值相同,或是两个值分别为 +0 和 -0 时,会返回true

示例:

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

在日常中使用===是没问题的。对于除了数值之外的值,===使用明确的语义进行比较:一个值只与自身全等。

非严格相等 ==

相等操作符比较两个值是否相等,在比较前将两个被比较的值转换为相同类型。在转换后(等式的一边或两边都可能被转换),最终的比较方式等同于全等操作符 === 的比较方式。 相等操作符满足交换律。

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

示例:

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); // true
console.log(num == str); // true
console.log(obj == str); // true
console.log(null == undefined); // true

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

部分开发者不建议使用==,因为===的结果更容易预测,并且由于没有隐式转换,===的操作会更快。

Object.is

Object.is方法来确定两个值是否相同。Object.is()===类似,区别是,对于符号零和NaN的处理。

示例:

Object.is(25, 25);                // true
Object.is('foo', 'foo');          // true
Object.is('foo', 'bar');          // false
Object.is(null, null);            // true
Object.is(undefined, undefined);  // true
Object.is(window, window);        // true
Object.is([], []);                // false
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);                // false
Object.is(-0, -0);                // true
Object.is(0n, -0n);               // true

Object.is(NaN, 0/0);              // true
Object.is(NaN, Number.NaN)        // true

Object.is内部采用的比较算法是SameValue(x, y)

SameValue和SameValueZero

ES6标准出版之前,是没有 SameValueZero 和 SameValue 这两个算法的。也就是说只有=====比较这两个算法:这两个算法有问题不能区分 NaN 以及 +0 和 -0。

SameValue可以区分NaN以及+0 和 -0。

SameValueZero 算法不能区分 +0 和 -0。

总结

在比较时,==执行类型转换,===只进行相同的比较,而不进行类型转换,也就是说,如果类型不同,会返回false。而Obj1ect.js和===相似,但是对于NaN和-0和+0进行了特殊处理。Object.js(NaN,NaN)返回true.