Array.prototype.includes与Array.prototype.indexOf


112

除了提高可读性,没有任何优势includesindexOf?他们似乎和我一样。

这有什么区别

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

还有这个?

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

12
includes对浏览器的支持要差得多。
昆汀

4
请注意,这includes不属于ES6 / ES2015。这是ECMAScript下一版本的提案,并将在今年添加。
菲利克斯·克林

4
只是想提一提,includesIE根本不支持它
ZvKa

Answers:


138

tl; dr: NaN区别对待:

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

提案中

动机

使用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比较算法而不是严格相等比较之外,这与上面的语义几乎相同,因此是[NaN].includes(NaN)正确的。

因此,该建议解决了现有代码中出现的两个问题。

为了一致性fromIndex,我们还添加了一个类似于Array.prototype.indexOf和的参数String.prototype.includes


更多信息:


1
真相只有一半。也不同:缺少的元素被视为undefined通过.includes(),并且不审议.indexOf()
罗伯·西默

11

目前,如果您对性能感到好奇,那么indexOf会更快,但是此JSperf测试倾向于显示更多的时间流逝,更多的时间includes()会比indexOf(我想会对其进行进一步优化)更快。

恕我直言,我也喜欢写,if (arr.includes(el)) {}因为它比它更清晰,更可维护if (arr.indexOf(el) !== -1) {}


1
似乎性能差异不是那么明显。我的移动Firefox显示,indexOf实际上更快。某些Chrome版本的行为相同...但是无论如何,今天的实现之间的差异似乎可以忽略不计。
Nux

8

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

数组中的用法

链接到ECMAScript规范)

  1. indexOf使用严格平等比较,includes使用SameValueZero算法。因此,出现以下两点差异。

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

let arr = [NaN];

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

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

字符串中的用法

链接到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

性能

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

历史

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

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


indexOftrue在明确设置undefined为数组后给出:let arr=[undefined];let arr=[];arr[0]=undefined;现在arr.indexOf(undefined) === 0
Jay Dadhania 19/12/28

您是唯一一个与表示差异的人undefined:原因是.includes将缺少的元素视为undefined,而.indexOf()忽略了它们。您也可以使用来“创建”缺少的元素arr[number beyond length] = whatever
罗伯·西默

没有人在索要琴弦,但您的言论暗示.includes()只吃琴弦。实际上,这两种方法都尽可能将任何内容强制转换为字符串。正则表达式被明确排除在考虑范围之外,.includes()允许根据当前草案在将来对标准进行添加。
罗伯特·西默

4

从概念上讲,当您要使用位置indexOf时,应仅使用indexOf来提取值或对数组进行操作,即在获取元素位置后使用切片,移位或分割。另一方面,使用Array.includes仅知道值是否在数组内,而不是位置,因为您不在乎它。


0

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

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

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


嗨,克鲁蒂,您已经回答了这个问题,并且已经接受了答案。此外,您可以看到答案如何仅包含其他答案中已经说过的信息。最后,这个问题已经有4年了。请提供有关最新问题或未回答问题的指导。谢谢
leonardfactory
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.