在 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