返回

Includes 引发的一系列思考

前端

对于JavaScript开发人员来说,Array.prototype.includes()方法是一个熟悉且方便的工具,它允许快速检查一个元素是否存在于数组中。然而,在某些情况下,使用includes()时可能会遇到一些意想不到的结果。本文将深入探讨includes()方法的细节,揭示可能导致意外结果的陷阱,并提供相应的解决方案。

首先,我们来看一个简单的示例:

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

在这个例子中,includes()方法正确地返回true,因为数字2存在于数组arr中。然而,如果我们尝试使用includes()来比较两个对象,结果就会变得有趣了:

const obj1 = { name: "John" };
const obj2 = { name: "John" };
console.log(arr.includes(obj1)); // false

在这个例子中,includes()方法返回false,即使obj1和obj2具有相同的属性值。这是因为在JavaScript中,对象是引用类型,这意味着它们存储的是对象的内存地址,而不是对象本身。因此,即使obj1和obj2具有相同的值,它们也是不同的对象,不会被includes()方法视为相等。

为了解决这个问题,我们可以使用一个称为Object.is()的函数。Object.is()函数会比较两个对象是否严格相等,这意味着它们必须是同一个对象或具有相同的值和类型。让我们用Object.is()来重写上面的示例:

const obj1 = { name: "John" };
const obj2 = { name: "John" };
console.log(Object.is(obj1, obj2)); // true

这次,Object.is()函数返回true,因为obj1和obj2是具有相同值和类型且是同一个对象。

includes()方法还可能会产生意外结果,当数组中的元素是函数时。例如:

const arr = [function() {}, function() {}];
console.log(arr.includes(function() {})); // false

在这个例子中,includes()方法返回false,即使数组arr中包含了一个匿名函数。这是因为在JavaScript中,函数也是引用类型,这意味着它们存储的是函数的内存地址,而不是函数本身。因此,即使匿名函数具有相同的代码,它们也是不同的函数,不会被includes()方法视为相等。

为了解决这个问题,我们可以使用一个称为Function.prototype.bind()的方法。Function.prototype.bind()方法可以创建一个新函数,该新函数与原始函数具有相同的代码,但具有不同的this值。让我们用Function.prototype.bind()来重写上面的示例:

const arr = [function() {}, function() {}];
const func1 = arr[0].bind({});
console.log(arr.includes(func1)); // true

这次,includes()方法返回true,因为func1和arr[0]是具有相同代码且具有相同this值的函数,因此被includes()方法视为相等。

总之,Array.prototype.includes()方法是一个强大的工具,但它也可能会产生意外的结果,尤其是当数组中的元素是对象或函数时。为了避免这些意外结果,我们可以使用Object.is()函数来比较对象,使用Function.prototype.bind()方法来比较函数。通过理解includes()方法的工作原理,并采用适当的解决方案,我们可以编写出更高效、更可靠的JavaScript代码。