JS `Object.is()`:更严格的值相等性判断,处理 `+0` `-0` 与 `NaN`

各位朋友,大家好!今天咱们不聊家长里短,就聊聊JavaScript里一个有点意思的函数:Object.is()。这玩意儿听着好像很高大上,其实就是个判断俩值是不是“绝对相等”的。但它又跟我们常用的===(严格相等)运算符有点不一样,区别就在于它对+0-0NaN的处理上。

咱们先来个热身,回顾一下===

console.log(1 === 1); // true
console.log("hello" === "hello"); // true
console.log(null === null); // true
console.log(undefined === undefined); // true
console.log({} === {}); // false (因为是不同的对象引用)
console.log([] === []); // false (同样因为是不同的数组引用)

=== 比较的是值和类型,如果类型不同,直接返回 false。如果类型相同,再比较值。对于对象和数组,比较的是引用是否相同,而不是内容是否相同。

现在,Object.is() 登场!

Object.is() 的基本用法

Object.is(value1, value2) 接受两个参数,返回一个布尔值,表示这两个值是否“绝对相等”。

console.log(Object.is(1, 1)); // true
console.log(Object.is("hello", "hello")); // true
console.log(Object.is(null, null)); // true
console.log(Object.is(undefined, undefined)); // true
console.log(Object.is({}, {})); // false (和 === 一样,比较的是引用)
console.log(Object.is([], [])); // false (和 === 一样,比较的是引用)

到目前为止,Object.is() 看起来和 === 没什么区别,对不对? 别急,好戏还在后头。

Object.is() 的特别之处:+0-0

在JavaScript里,+0-0 是两个不同的值,虽然它们在数值上都表示零。 === 认为它们是相等的:

console.log(+0 === -0); // true

但是,Object.is() 区分了它们:

console.log(Object.is(+0, -0)); // false

这有什么用呢? 在一些特定的数学运算或者算法中,+0-0 的符号是有意义的,区分它们可以帮助我们避免一些潜在的错误。 举个例子,计算 1 / x 的结果时,如果 x+0,结果是 Infinity;如果 x-0,结果是 -Infinity

console.log(1 / +0); // Infinity
console.log(1 / -0); // -Infinity

如果你的程序依赖于这种符号差异,那么 Object.is() 就能派上用场了。

Object.is() 的另一个特别之处:NaN

NaN (Not a Number) 是 JavaScript 中一个特殊的值,表示一个非数字的结果。 NaN 有一个奇怪的特性:它和任何值都不相等,包括它自己!

console.log(NaN === NaN); // false

这让人很困惑,因为我们通常认为一个东西应该和它自己相等。 Object.is() 修正了这个问题:

console.log(Object.is(NaN, NaN)); // true

Object.is() 认为 NaNNaN 是相等的。 这使得在某些情况下更容易判断一个值是否为 NaN

Object.is() 的应用场景

虽然 Object.is() 看起来只是对 === 的一个小小的补充,但在某些情况下,它能提供更精确的相等性判断。

  1. 需要区分 +0-0 的情况: 如前所述,在一些数学运算或算法中,+0-0 的符号是有意义的。

  2. 需要正确判断 NaN 的情况: 由于 NaN 不等于自身,使用 Object.is(NaN, NaN) 可以更可靠地判断一个值是否为 NaN。 当然,你也可以使用 Number.isNaN() 函数,它专门用于判断一个值是否为 NaN

console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN(123)); // false
  1. 某些库或框架内部使用: 一些库或框架可能会使用 Object.is() 来实现更严格的相等性判断,以确保程序的正确性。

Object.is() vs. === vs. ==

为了更好地理解 Object.is() 的作用,我们来对比一下 Object.is()===(严格相等)和 ==(相等)这三种相等性判断方式。

特性 == (相等) === (严格相等) Object.is() (绝对相等)
类型转换 会进行类型转换 不进行类型转换 不进行类型转换
+0-0 认为相等 认为相等 认为不相等
NaN 认为不等于自身 认为不等于自身 认为等于自身
使用场景 尽量避免使用,容易出错 常用,推荐使用 特殊场景,需要区分 +0-0,以及正确判断 NaN

== 是最宽松的相等性判断,它会进行类型转换。 由于类型转换的规则比较复杂,容易导致一些意想不到的结果,因此通常不建议使用。

console.log(1 == "1"); // true (字符串 "1" 会被转换为数字 1)
console.log(0 == false); // true (false 会被转换为数字 0)
console.log(null == undefined); // true

=== 是更严格的相等性判断,它不会进行类型转换。 这是我们通常使用的相等性判断方式。

Object.is() 是最严格的相等性判断,它在 === 的基础上,对 +0-0NaN 进行了特殊处理。

手写一个 Object.is()

为了更好地理解 Object.is() 的实现原理,我们可以尝试手写一个简单的 Object.is() 函数:

function myObjectIs(x, y) {
  if (x === y) {
    // 针对 +0 和 -0 的情况
    return x !== 0 || 1 / x === 1 / y;
  } else {
    // 针对 NaN 的情况
    return x !== x && y !== y;
  }
}

console.log(myObjectIs(1, 1)); // true
console.log(myObjectIs("hello", "hello")); // true
console.log(myObjectIs(+0, -0)); // false
console.log(myObjectIs(NaN, NaN)); // true
console.log(myObjectIs(NaN, 1)); // false

这个 myObjectIs() 函数首先判断 xy 是否严格相等。 如果严格相等,再判断是否为 +0-0 的情况。 如果不严格相等,则判断是否为 NaN 的情况。

总结

Object.is() 是 JavaScript 中一个用于判断两个值是否“绝对相等”的函数。 它在 === 的基础上,对 +0-0NaN 进行了特殊处理。

  • Object.is(+0, -0) 返回 false,而 === 返回 true
  • Object.is(NaN, NaN) 返回 true,而 === 返回 false

Object.is() 在一些需要区分 +0-0,以及正确判断 NaN 的特殊场景中非常有用。

总的来说,=== 是我们最常用的相等性判断方式。只有在需要处理 +0-0NaN 的特殊情况下,才需要使用 Object.is()。 就像工具箱里的扳手和螺丝刀,各有各的用途,用对了才能事半功倍!

今天就先聊到这儿,希望大家对 Object.is() 有了更深入的了解。 如果有什么问题,欢迎随时提问。 下次有机会,咱们再聊聊 JavaScript 里的其他有趣的东西!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注