The `Array.prototype.includes()` method
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 forfromIndex
(optional): The index to start searching from (default is 0)
The method returns a boolean:
true
: If the element is foundfalse
: 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
- Simple Existence Check:
const permissions = ['read', 'write', 'execute'];
if (permissions.includes('write')) {
// Perform write operation
}
- 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');
}
- 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
- Sparse Arrays:
const sparseArray = [1, , 3];
console.log(sparseArray.includes(undefined)); // false
- 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
- 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
- Python:
arr = [1, 2, 3]
print(2 in arr) # True
- Ruby:
arr = [1, 2, 3]
puts arr.include?(2) # true
- 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
- 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 />}
- Computed Properties in Vue:
new Vue({
data: {
cartItems: ['apple', 'banana', 'orange']
},
computed: {
hasBanana() {
return this.cartItems.includes('banana');
}
}
});
Advanced Usage Examples
- 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
- 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
- Combining with the Exponentiation Operator:
const powers = [1, 2, 4, 8, 16];
const number = 2 ** 3; // 8
console.log(powers.includes(number)); // true
- 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()方法
下一篇:指数运算符(**)