解决 ES9 中 Array.prototype.includes() 方法 NaN 判断错误问题

在 ES9 中,新增了一个方法 Array.prototype.includes(),用于判断数组中是否包含某个元素。这个方法非常方便,但是它有一个缺陷,就是无法正确判断数组中的 NaN 值。

具体来说,在数组中使用 includes() 方法时,如果数组中包含 NaN,那么无论传入的参数是什么,都会返回 false。例如:

const arr = [1, NaN, 3];
console.log(arr.includes(NaN)); // false

这是因为在 JavaScript 中,NaN 与任何值都不相等,包括它自己。因此在使用 includes() 方法时,需要特别注意。

那么如何解决这个问题呢?

解决方法主要有两种:

方法一:手动遍历数组

我们可以手动遍历数组,在遍历过程中使用 isNaN() 方法判断当前元素是否是 NaN。如果是 NaN,则返回 true,否则继续遍历。如果最终遍历完成,仍未找到 NaN,则返回 false。

Array.prototype.includesNaN = function() {
  for (let i = 0; i < this.length; i++) {
    if (isNaN(this[i])) {
      return true;
    }
  }
  return false;
};

这样,我们就可以使用 includesNaN() 方法来判断数组中是否包含 NaN。

const arr = [1, NaN, 3];
console.log(arr.includesNaN()); // true
console.log(arr.includes(2)); // false

但是,这种方法需要手动遍历数组,代码比较冗长。因此,我们可以选择第二种方法。

方法二:使用 Symbol.hasInstance

ES6 中新增了一个特殊的 Symbol,叫做 Symbol.hasInstance。这个 Symbol 可以用来为某个对象定义一个函数,当使用 instanceof 运算符判断对象是否是该类型时,会自动调用这个函数。

我们可以使用 Symbol.hasInstance 来为数组定义一个判断 NaN 的函数,这样就可以直接使用 includes() 方法判断了。

const hasNaN = {
  [Symbol.hasInstance]: x => isNaN(x)
};

const arr = [1, NaN, 3];
console.log(arr.includes(NaN, -1)); // true
console.log(arr.includes(2)); // false

这里,我们首先定义一个对象 hasNaN,该对象有一个 Symbol.hasInstance 方法,用来判断传入的值是否为 NaN。然后,我们将这个对象传给数组的 constructor 属性,这样数组就可以使用 includes() 方法判断 NaN 了。

总结

两种方法都可以解决 ES9 中 includes() 方法无法正确判断 NaN 的问题。但是,第二种方法更加简洁和直观,因此更推荐使用。另外,需要注意的是,在使用 includes() 方法时,如果传入了第二个参数 fromIndex,则需要使用第二种方法,并将 hasNaN 对象直接传给数组的 includes() 方法。

const arr = [1, NaN, 3];
console.log(arr.includes(NaN, -1)); // true
console.log(arr.includes(2, -1)); // false

希望这篇文章对你有所帮助!

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65abcaa9add4f0e0ff573a0d