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 【问题描述】:除了提高可读性之外,includes
比 indexOf
有什么优势吗?他们看起来和我一模一样。
这有什么区别
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) > -1
是 false
[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.indexOf
和String.prototype.includes
,以保持一致性。
更多信息:
SameValueZero
algorithm
Strict Equality Comparison
algorithm
【讨论】:
只对了一半。也有所不同:缺少的元素被.includes()
视为undefined
,而不被.indexOf()
考虑。【参考方案2】:
从技术上讲,唯一的区别是如何处理NaN
和undefined
。使用 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
显式设置为数组后给出true
:let 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()
返回一个布尔值(true
或 false
)。
【讨论】:
您好 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()