Array.prototype.includes 与 Array.prototype.indexOf

Posted

技术标签:

【中文标题】Array.prototype.includes 与 Array.prototype.indexOf【英文标题】:Array.prototype.includes vs. Array.prototype.indexOf 【发布时间】:2016-05-24 01:15:40 【问题描述】:

除了提高可读性之外,includesindexOf 有什么优势吗?他们看起来和我一模一样。

这有什么区别

var x = [1,2,3].indexOf(1) > -1; //true

还有这个?

var y = [1,2,3].includes(1); //true

【问题讨论】:

includes 的浏览器支持更差。 请注意,includes 不是 ES6/ES2015 的一部分。这是对下一版 ECMAScript 的提议,今年会加入。 只想提一下,IE 根本不支持includes includes 比 indexOf 慢大约 50 倍,至少在 Chrome 中是这样。当心! @SevenSystems 你有什么可以证明这一点的吗? 【参考方案1】:

tl;dr: NaN 被区别对待:

[NaN].indexOf(NaN) > -1false [NaN].includes(NaN)true

来自proposal:

动机

使用 ECMAScript 数组时,通常需要确定数组是否包含元素。流行的模式是

if (arr.indexOf(el) !== -1) 
    ...

具有各种其他可能性,例如arr.indexOf(el) >= 0,甚至是~arr.indexOf(el)

这些模式表现出两个问题:

他们没有“说出你的意思”:不是询问数组是否包含一个元素,而是询问该元素在数组中第一次出现的索引是什么,然后比较它或对其进行位旋转, 以确定您实际问题的答案。 NaN 失败,因为 indexOf 使用严格相等比较,因此 [NaN].indexOf(NaN) === -1

建议的解决方案

我们建议增加一个Array.prototype.includes 方法,这样上面的模式就可以改写为

if (arr.includes(el)) 
    ...

这与上面的语义几乎相同,只是它使用 SameValueZero 比较算法而不是 Strict Equality Comparison,从而使 [NaN].includes(NaN) 为真。

因此,这个提议解决了现有代码中的两个问题。

我们额外添加了一个fromIndex 参数,类似于Array.prototype.indexOfString.prototype.includes,以保持一致性。


更多信息:

SameValueZero algorithm Strict Equality Comparison algorithm

【讨论】:

只对了一半。也有所不同:缺少的元素被.includes() 视为undefined,而不被.indexOf() 考虑。【参考方案2】:

从技术上讲,唯一的区别是如何处理NaNundefined。使用 indexOf

时,它们将找不到

arr.indexOf('blah') !== -1可读性和可维护性较差。另一方面,arr.includes('blah') 按照它所说的做,很明显它返回了一个boolean

includes 也没有用如果你想知道字符串在数组中的位置

关于性能:根据this article 的主题,没有明显差异,尽管includes 可能会慢一点。

indexOf 是在 includes 之前创建的。

【讨论】:

似乎性能上的差异并不那么明显。我的移动 Firefox 显示 indexOf 实际上更快。一些 Chrome 版本的行为相同......但在今天的实施中,差异似乎可以忽略不计。 刚刚打开一个控制台并测试了它:let allElements = [...document.getElementsByTagName('*')]; let t1 = performance.now(); for(let i=0;i<1e7;i++) randEl = allElements[Math.floor(Math.random()*allElements.length)]; const isIn = allElements.includes(randEl); let t2 = performance.now(); for(let i=0;i<1e7;i++) randEl = allElements[Math.floor(Math.random()*allElements.length)]; const isIn = (allElements.indexOf(randEl)>-1); let t3 = performance.now(); console.log('Include time:', t2-t1); console.log('indexOd time:', t3-t2); 结果:包括快 40 倍。【参考方案3】:

.indexOf().includes() 方法可用于搜索数组中的元素或搜索给定字符串中的字符/子字符串。

在数组中的使用

(Link 到 ECMAScript 规范)

    indexOf 使用Strict Equality Comparison 而includes 使用SameValueZero 算法。由于这个原因,产生了以下两点差异。

    正如Felix Kling 所指出的,NaN 的行为是不同的。

let arr = [NaN];

arr.indexOf(NaN); // returns -1; meaning NaN is not present
arr.includes(NaN); // returns true
    undefined 的行为也有所不同。
let arr = [ , , ];

arr.indexOf(undefined); // returns -1; meaning undefined is not present
arr.includes(undefined); // returns true

在字符串中的使用

(Link 到 ECMAScript 规范)

1。 如果您将 RegExp 传递给 indexOf,它会将 RegExp 视为字符串并返回字符串的索引(如果找到)。但是,如果您将 RegExp 传递给 includes,它将引发异常。

let str = "javascript";

str.indexOf(/\w/); // returns -1 even though the elements match the regex because /\w/ is treated as string
str.includes(/\w/); // throws TypeError: First argument to String.prototype.includes must not be a regular expression

性能

正如GLAND_PROPRE 指出的那样,includes 可能比indexOf 慢一点(非常小)(因为它需要检查正则表达式作为第一个参数),但实际上,这不会差别很大,可以忽略不计。

历史

String.prototype.includes() 是在 ECMAScript 2015 中引入的,而Array.prototype.includes() 是在 ECMAScript 2016 中引入的。关于浏览器支持,请明智地使用它们。

String.prototype.indexOf()Array.prototype.indexOf() 存在于 ECMAScript 的 ES5 版本中,因此受到所有浏览器的支持。

【讨论】:

indexOf 在将undefined 显式设置为数组后给出truelet arr=[undefined];let arr=[];arr[0]=undefined; 现在arr.indexOf(undefined) === 0 您是唯一指出与undefined 不同的人:原因是.includes 将缺少的元素视为undefined,而.indexOf() 会忽略它们。您还可以使用arr[number beyond length] = whatever“创建”缺失的元素。 没有人要求字符串,但您的言论表明.includes() 只吃字符串。实际上,这两种方法都尽可能地将任何内容强制为字符串。根据当前草案,正则表达式被明确排除在 .includes() 的参数中,以允许将来添加到标准中【参考方案4】:

从概念上讲,当您想使用位置时,您应该使用 indexOf另一方面,使用 Array.includes 只知道值是否在数组内部而不是位置,因为您不关心它。

【讨论】:

如果您想支持旧浏览器,请使用 indexOf,这通常是个好主意。如果您的代码不会在浏览器中执行,请使用包含,因此您知道您不需要支持像 IE 这样的旧浏览器,我保证您仍然在使用它们。如果您需要测试诸如 NaN 或 undefined 之类的值并且仍想支持旧浏览器,请不要使用。只需使用老式的 for 循环即可。对于那些不知道 IE 不是现代浏览器或因为他们在公共/工作计算机上而别无选择的人来说,编写一个 for 循环并支持 IE 并不可耻。【参考方案5】:

indexOf()includes() 都可以用于查找数组中的元素,但是每个函数会产生不同的返回值。

indexOf 返回一个数字(-1 如果数组中不存在元素,或者如果元素存在则返回数组位置)。

includes() 返回一个布尔值(truefalse)。

【讨论】:

您好 Kruti,这个问题已经得到解答,并且已被接受。此外,您可以看到您的答案如何仅包含其他答案中已经说过的信息。最后,这个问题已经 4 岁了。请提供有关最新问题或未回答问题的指导。谢谢【参考方案6】:

Internet Explorer 不支持包含,如果这有助于您做出决定。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes#Browser_compatibility

【讨论】:

【参考方案7】:

答案和例子都很棒。然而(乍一看),这让我误解了includes 在使用undefined 时总是会返回true

因此我包含示例来详细说明包含可用于检查未定义和 NaN 值其中 indexOf 不能

//Array without undefined values and without NaN values. 
//includes will return false because there are no NaN and undefined values

const myarray = [1,2,3,4]

console.log(myarray.includes(undefined)) //returns false
console.log(myarray.includes(NaN)) //returns false


//Array with undefined values and Nan values.
//includes will find them and return true

const myarray2 = [1,NaN, ,4]

console.log(myarray2.includes(undefined)) //returns true
console.log(myarray2.includes(NaN)) //returns true


console.log(myarray2.indexOf(undefined) > -1) //returns false
console.log(myarray2.indexOf(NaN) > -1) //returns false

总结

includes 用于检查数组中未定义和 NaN 值 indexOf 不能用于检查数组中的未定义和 NaN 值

【讨论】:

【参考方案8】:

indexOf 是检查数组中是否有东西的旧方法,新方法更好,因为您不必为存在 (-1) 编写条件,这就是为什么使用 include() 方法返回一个布尔值。

array.indexOf('something')      // return index or -1
array.includes('something')     // return true of false

所以对于查找索引,第一种方法更好,但对于检查是否存在,第二种方法更有用。

【讨论】:

if(array.includes('something')) //doSomething if(array.indexOf('something') > -1) //doSomething - 这两者之间的差异是 > -1, const incls = array.includes('something') || const inOf = array.indexOf('something') > -1;返回真或假。差别不大【参考方案9】:

includes 使用自动类型转换,即在字符串和数字之间。 indexOf 没有。

【讨论】:

【参考方案10】:
 
let allGroceries = ['tomato', 'baked bean',];
 
//returns true or false
console.log(allGroceries.includes("tomato")); //uses boolean value to check 

let fruits2 = ["apple", "banana", "orange"];
console.log(fruits2.includes("banana"));
// returns true because banana is in the array



//.indexOf returns the index of the value

console.log(allGroceries.indexOf("tomato"));//returns the index of the value
//returns -1 because tomato is not in the array
//fromIndex
console.log(allGroceries.indexOf("tomato", 2));


【讨论】:

以上是关于Array.prototype.includes 与 Array.prototype.indexOf的主要内容,如果未能解决你的问题,请参考以下文章

[ES2016] Check if an array contains an item using Array.prototype.includes

有了 indexOf,为什么 ECMAScript 7 还添加了 Array.prototype.includes

ES7(2016)Array.prototype.includes()

ES7的新特性

如何为 JS Array.includes() 提供 equals/hash 函数? [复制]

es7,es8