阿里云主机折上折
  • 微信号
Current Site:Index > The `Array.prototype.includes()` method

The `Array.prototype.includes()` method

Author:Chuan Chen 阅读数:21806人阅读 分类: JavaScript

ECMAScript 7 Array.prototype.includes() Method

ECMAScript 7 introduced the Array.prototype.includes() method to determine whether an array contains a specific element. This method addresses several pain points of the indexOf() method when checking for element existence, such as its inability to correctly identify NaN and the need to explicitly check if the return value is not -1.

Basic Syntax and Parameters

The syntax of the includes() method is very simple:

arr.includes(valueToFind[, fromIndex])

It accepts two parameters:

  • valueToFind: The element value to search for
  • fromIndex (optional): The index to start searching from (default is 0)

The method returns a boolean:

  • true: If the element is found
  • false: If the element is not found

Comparison with the indexOf() Method

Before ES7, we typically used the indexOf() method to check for element existence:

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

The includes() method provides a more intuitive syntax:

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

Handling the Special Case of NaN

A major improvement of the includes() method is its ability to correctly handle NaN searches. In JavaScript, NaN is not equal to any value, including itself:

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

indexOf() cannot correctly find NaN:

const arr = [1, NaN, 3];
console.log(arr.indexOf(NaN)); // -1 (not found)

But includes() can:

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

Using the fromIndex Parameter

The fromIndex parameter specifies the starting position for the search:

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

// Start searching from index 2
console.log(arr.includes(2, 2)); // true (finds the second 2)
console.log(arr.includes(2, 3)); // false (not found)

If fromIndex is greater than or equal to the array length, it directly returns false:

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

A negative fromIndex is calculated from the end of the array:

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

Typed Arrays and Array-like Objects

The includes() method can also be used with typed arrays (TypedArray):

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

For array-like objects, they need to be converted to arrays first:

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

Performance Considerations

In most cases, the performance difference between includes() and indexOf() is negligible. However, for frequent searches in large arrays, indexOf() might be slightly faster because it only needs to return the index of the first match, whereas includes() needs to traverse the entire array until a match is found.

Practical Use Cases

  1. Simple Existence Check:
const permissions = ['read', 'write', 'execute'];
if (permissions.includes('write')) {
  // Perform write operation
}
  1. Form Validation:
const validExtensions = ['.jpg', '.png', '.gif'];
const fileExtension = getFileExtension(); // Assume this is a function to get the file extension

if (!validExtensions.includes(fileExtension.toLowerCase())) {
  alert('Invalid file type');
}
  1. Feature Detection:
// Check if the browser supports a specific API
const supportedAPIs = ['fetch', 'Promise', 'IntersectionObserver'];
if (!supportedAPIs.includes('IntersectionObserver')) {
  // Load polyfill
}

Combining with Other Array Methods

includes() can be combined with other array methods to create more powerful logic:

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

// Find even numbers in `numbers` that are not in `evenNumbers`
const missingEvens = numbers.filter(
  num => num % 2 === 0 && !evenNumbers.includes(num)
);
console.log(missingEvens); // []

Edge Cases and Considerations

  1. Sparse Arrays:
const sparseArray = [1, , 3];
console.log(sparseArray.includes(undefined)); // false
  1. Object References: includes() uses strict equality (===) for comparison, so objects are compared by reference:
const obj = {name: 'John'};
const arr = [{name: 'John'}, obj];
console.log(arr.includes({name: 'John'})); // false
console.log(arr.includes(obj)); // true
  1. Prototype Chain Properties:
function MyArray() {}
MyArray.prototype = Array.prototype;
const myArr = new MyArray();
myArr.push(1, 2, 3);
console.log(myArr.includes(2)); // true

Browser Compatibility and Polyfill

Although modern browsers support includes(), older browsers may require a 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;
  };
}

Comparison with Similar Methods in Other Languages

  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

Usage in Frameworks and Libraries

  1. Conditional Rendering in React:
const allowedRoles = ['admin', 'editor'];
const userRole = getUserRole(); // Assume this is a function to get the user's role

{allowedRoles.includes(userRole) && <AdminPanel />}
  1. Computed Properties in Vue:
new Vue({
  data: {
    cartItems: ['apple', 'banana', 'orange']
  },
  computed: {
    hasBanana() {
      return this.cartItems.includes('banana');
    }
  }
});

Advanced Usage Examples

  1. Case-Insensitive includes Implementation:
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. Deep includes Implementation:
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

Combining with Other ES7 Features

  1. Combining with the Exponentiation Operator:
const powers = [1, 2, 4, 8, 16];
const number = 2 ** 3; // 8
console.log(powers.includes(number)); // true
  1. Combining with async/await:
async function checkFeatureAvailability(features, featureName) {
  if (!Array.isArray(features)) {
    features = await fetchFeatures();
  }
  return features.includes(featureName);
}

Test Case Examples

To ensure a correct understanding of includes() behavior, you can write some test cases:

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()方法

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

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.