阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > Array.prototype.includes()方法

Array.prototype.includes()方法

作者:陈川 阅读数:21804人阅读 分类: JavaScript

ECMAScript 7 Array.prototype.includes()方法

ECMAScript 7引入了Array.prototype.includes()方法,用于判断数组是否包含某个特定元素。这个方法解决了indexOf()方法在判断元素存在时的几个痛点,比如无法正确识别NaN,以及需要显式检查返回值是否不等于-1。

基本语法和参数

includes()方法的语法非常简单:

arr.includes(valueToFind[, fromIndex])

它接受两个参数:

  • valueToFind:需要查找的元素值
  • fromIndex(可选):从哪个索引开始查找,默认为0

方法返回一个布尔值:

  • true:如果找到该元素
  • false:如果未找到该元素

与indexOf()方法的比较

在ES7之前,我们通常使用indexOf()方法来判断元素是否存在:

const arr = [1, 2, 3];
if (arr.indexOf(2) !== -1) {
  console.log('Found');
}

includes()方法提供了更直观的语法:

const arr = [1, 2, 3];
if (arr.includes(2)) {
  console.log('Found');
}

处理NaN的特殊情况

includes()方法的一个重大改进是它能正确处理NaN的查找。在JavaScript中,NaN不等于任何值,包括它自己:

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

indexOf()无法正确查找NaN

const arr = [1, NaN, 3];
console.log(arr.indexOf(NaN)); // -1 (找不到)

includes()可以:

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

fromIndex参数的使用

fromIndex参数指定开始搜索的位置:

const arr = [1, 2, 3, 2, 1];

// 从索引2开始搜索
console.log(arr.includes(2, 2)); // true (找到第二个2)
console.log(arr.includes(2, 3)); // false (找不到)

如果fromIndex大于或等于数组长度,直接返回false

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

负值的fromIndex会从数组末尾开始计算:

const arr = [1, 2, 3];
console.log(arr.includes(2, -2)); // true (从索引1开始)
console.log(arr.includes(1, -1)); // false (从索引2开始)

类型数组和类数组对象

includes()方法也可以用于类型数组(TypedArray):

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

但对于类数组对象,需要先转换为数组:

const arrayLike = {0: 'a', 1: 'b', length: 2};
console.log(Array.prototype.includes.call(arrayLike, 'b')); // true

性能考虑

在大多数情况下,includes()indexOf()的性能差异可以忽略不计。但在大型数组中进行频繁查找时,indexOf()可能稍微快一些,因为它只需要返回第一个匹配项的索引,而includes()需要遍历整个数组直到找到匹配项。

实际应用场景

  1. 简单的存在性检查
const permissions = ['read', 'write', 'execute'];
if (permissions.includes('write')) {
  // 执行写操作
}
  1. 表单验证
const validExtensions = ['.jpg', '.png', '.gif'];
const fileExtension = getFileExtension(); // 假设这是一个获取文件扩展名的函数

if (!validExtensions.includes(fileExtension.toLowerCase())) {
  alert('无效的文件类型');
}
  1. 功能检测
// 检测浏览器是否支持某个API
const supportedAPIs = ['fetch', 'Promise', 'IntersectionObserver'];
if (!supportedAPIs.includes('IntersectionObserver')) {
  // 加载polyfill
}

与其他数组方法的结合

includes()可以与其他数组方法结合使用,创建更强大的逻辑:

const numbers = [1, 2, 3, 4, 5];
const evenNumbers = [2, 4, 6];

// 找出numbers中不在evenNumbers中的偶数
const missingEvens = numbers.filter(
  num => num % 2 === 0 && !evenNumbers.includes(num)
);
console.log(missingEvens); // []

边界情况和注意事项

  1. 稀疏数组
const sparseArray = [1, , 3];
console.log(sparseArray.includes(undefined)); // false
  1. 对象引用includes()使用严格相等(===)比较,所以对象比较的是引用:
const obj = {name: 'John'};
const arr = [{name: 'John'}, obj];
console.log(arr.includes({name: 'John'})); // false
console.log(arr.includes(obj)); // true
  1. 原型链上的属性
function MyArray() {}
MyArray.prototype = Array.prototype;
const myArr = new MyArray();
myArr.push(1, 2, 3);
console.log(myArr.includes(2)); // true

浏览器兼容性和polyfill

虽然现代浏览器都支持includes(),但在旧版浏览器中可能需要polyfill:

if (!Array.prototype.includes) {
  Array.prototype.includes = function(searchElement, fromIndex) {
    if (this == null) {
      throw new TypeError('"this" is null or not defined');
    }

    var o = Object(this);
    var len = o.length >>> 0;

    if (len === 0) {
      return false;
    }

    var n = fromIndex | 0;
    var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);

    function sameValueZero(x, y) {
      return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y));
    }

    while (k < len) {
      if (sameValueZero(o[k], searchElement)) {
        return true;
      }
      k++;
    }

    return false;
  };
}

与其他语言中的类似方法比较

  1. Python
arr = [1, 2, 3]
print(2 in arr)  # True
  1. Ruby
arr = [1, 2, 3]
puts arr.include?(2)  # true
  1. Java
import java.util.Arrays;
List<Integer> list = Arrays.asList(1, 2, 3);
System.out.println(list.contains(2));  // true

在框架和库中的应用

  1. React中的条件渲染
const allowedRoles = ['admin', 'editor'];
const userRole = getUserRole(); // 假设这是一个获取用户角色的函数

{allowedRoles.includes(userRole) && <AdminPanel />}
  1. Vue中的计算属性
new Vue({
  data: {
    cartItems: ['apple', 'banana', 'orange']
  },
  computed: {
    hasBanana() {
      return this.cartItems.includes('banana');
    }
  }
});

高级用法示例

  1. 实现一个不区分大小写的includes
function caseInsensitiveIncludes(arr, value) {
  return arr.some(item => 
    String(item).toLowerCase() === String(value).toLowerCase()
  );
}

const fruits = ['Apple', 'Banana', 'Orange'];
console.log(caseInsensitiveIncludes(fruits, 'apple')); // true
  1. 深度includes实现
function deepIncludes(arr, value) {
  return arr.some(item => JSON.stringify(item) === JSON.stringify(value));
}

const complexArray = [{a: 1}, {b: 2, c: [3, 4]}];
console.log(deepIncludes(complexArray, {b: 2, c: [3, 4]})); // true

与其他ES7特性的结合使用

  1. 与指数运算符结合
const powers = [1, 2, 4, 8, 16];
const number = 2 ** 3; // 8
console.log(powers.includes(number)); // true
  1. 与async/await结合
async function checkFeatureAvailability(features, featureName) {
  if (!Array.isArray(features)) {
    features = await fetchFeatures();
  }
  return features.includes(featureName);
}

测试用例示例

为了确保正确理解includes()的行为,可以编写一些测试用例:

const testCases = [
  { input: [[1, 2, 3], 2], expected: true },
  { input: [[1, 2, 3], 4], expected: false },
  { input: [[1, NaN, 3], NaN], expected: true },
  { input: [['a', 'b', 'c'], 'a'], expected: true },
  { input: [[1, 2, 3], '1'], expected: false },
  { input: [[1, 2, 3], 2, 1], expected: true },
  { input: [[1, 2, 3], 1, 1], expected: false },
];

testCases.forEach(({input, expected}) => {
  const result = Array.prototype.includes.apply(input[0], input.slice(1));
  console.assert(
    result === expected,
    `Failed: [${input[0]}].includes(${input.slice(1).join(', ')}) ` +
    `expected ${expected} but got ${result}`
  );
});

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

上一篇:Promise.all()方法

下一篇:指数运算符(**)

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌