Array.prototype.includes frente a Array.prototype.indexOf

112

Más allá de la legibilidad mejorada, ¿hay alguna ventaja para includesover indexOf? Me parecen idénticos.

Cual es la diferencia entre esto

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

¿Y esto?

var y = [1,2,3].includes(1); //true
Mate
fuente
12
includestiene un soporte de navegador mucho peor.
Quentin
4
Tenga en cuenta que includesno forma parte de ES6 / ES2015. Es una propuesta para la próxima versión de ECMAScript y se agregará este año.
Felix Kling
4
Solo quería mencionar también que includesNO es compatible con IE en absoluto
ZvKa

Respuestas:

138

tl; dr: NaN se trata de manera diferente:

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

De la propuesta :

Motivación

Cuando se utilizan matrices ECMAScript, normalmente se desea determinar si la matriz incluye un elemento. El patrón predominante para esto es

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

con varias otras posibilidades, por ejemplo arr.indexOf(el) >= 0, o incluso ~arr.indexOf(el).

Estos patrones presentan dos problemas:

  • No logran "decir lo que quieres decir": en lugar de preguntar si la matriz incluye un elemento, preguntas cuál es el índice de la primera aparición de ese elemento en la matriz y luego lo comparas o lo intercambias para determinar la respuesta a su pregunta real.
  • Fallan NaN, ya que indexOfutiliza la comparación estricta de igualdad y por lo tanto [NaN].indexOf(NaN) === -1.

Solución propuesta

Proponemos la adición de un Array.prototype.includesmétodo, de modo que los patrones anteriores se puedan reescribir como

if (arr.includes(el)) {
    ...
}

Esto tiene casi la misma semántica que la anterior, excepto que usa el algoritmo de comparación SameValueZero en lugar de la Comparación de igualdad estricta, por lo que se hace [NaN].includes(NaN)verdadero.

Así, esta propuesta resuelve ambos problemas vistos en el código existente.

Además, agregamos un fromIndexparámetro, similar a Array.prototype.indexOfy String.prototype.includes, para mayor coherencia.


Más información:

Felix Kling
fuente
1
Solo la mitad de la verdad. También es diferente: los elementos faltantes se tratan como undefinedpor .includes()y no son considerados por .indexOf().
Robert Siemer
11

Si te preguntas sobre el rendimiento, por el momento indexOf es más rápido, pero esta prueba JSperf tiende a mostrar que cuanto más pase el tiempo, más includes()será más rápido queindexOf (supongo que se optimizará aún más).

En mi humilde opinión, también prefiero escribir if (arr.includes(el)) {}ya que es más claro y más fácil de mantener queif (arr.indexOf(el) !== -1) {}

538ROMEO
fuente
1
Parece que la diferencia en el rendimiento no es tan obvia. Mi móvil Firefox muestra que indexOf es en realidad más rápido. Algunas versiones de Chrome actúan de la misma manera ... Pero la diferencia parece insignificante de todos modos en las implementaciones actuales.
Nux
8

.indexOf()y los .includes()métodos se pueden usar para buscar un elemento en una matriz o para buscar un carácter / subcadena en una cadena dada.

Uso en matriz

( Enlace a la especificación ECMAScript)

  1. indexOfusa la comparación estricta de igualdad mientras que includesusa el algoritmo SameValueZero . Por esta razón, surgen los siguientes dos puntos de diferencias.

  2. Como señala Felix Kling , el comportamiento es diferente en caso deNaN .

let arr = [NaN];

arr.indexOf(NaN); // returns -1; meaning NaN is not present
arr.includes(NaN); // returns true
  1. El comportamiento también es diferente en el caso de undefined.
let arr = [ , , ];

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

Uso en cadena

( Enlace a la especificación ECMAScript)

  1. Si pasa una RegExp a indexOf, tratará la RegExp como una cadena y devolverá el índice de la cadena, si se encuentra. Sin embargo, si pasa una expresión regular aincludes , generará una excepción.
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

Actuación

Como 538ROMEO señaló , includespuede ser un poco (muy pequeño) un poco más lento (ya que necesita verificar una expresión regular como primer argumento) queindexOf pero en realidad, esto no hace mucha diferencia y es insignificante.

Historia

String.prototype.includes() se introdujo en ECMAScript 2015 mientras que Array.prototype.includes() se introdujo en ECMAScript 2016. Con respecto a la compatibilidad con el navegador, utilícelos con prudencia.

String.prototype.indexOf()y Array.prototype.indexOf()están presentes en la edición ES5 de ECMAScript y, por lo tanto, son compatibles con todos los navegadores.

Srishti
fuente
indexOfda truedespués de establecer explícitamente undefineden una matriz: let arr=[undefined];o let arr=[];arr[0]=undefined;Ahoraarr.indexOf(undefined) === 0
Jay Dadhania
Usted es el único que indica la diferencia con undefined: La razón es que .includestrata los elementos faltantes como undefined, mientras que los .indexOf()ignora. También puede "crear" elementos faltantes con arr[number beyond length] = whatever.
Robert Siemer
Nadie estaba pidiendo cuerdas, pero sus comentarios sugieren que .includes()solo come cuerdas. En realidad, ambos métodos coaccionan cualquier cosa a una cuerda tan bien como pueden. Expresiones regulares se excluye específicamente como argumento para .includes()a permitir futuras ampliaciones de la norma de acuerdo con el proyecto actual.
Robert Siemer
4

Conceptualmente, debes usar indexOf cuando quieras usar la posición indexOf, solo dale para extraer el valor u operar sobre la matriz, es decir, usando slice, shift o split después de obtener la posición del elemento. Por otro lado, Use Array.incluye solo para saber si el valor está dentro de la matriz y no la posición porque no le importa.

Sebastián Gómez
fuente
0

indexOf()y includes()ambos se pueden usar para buscar elementos en una matriz, sin embargo, cada función produce valores de retorno diferentes.

indexOf devuelve un número-1 si el elemento no está presente en la matriz, o la posición de la matriz si el elemento está presente).

includes()devuelve un valor booleano ( trueo false).

Kruti
fuente
Hola Kruti, esta pregunta ya ha sido respondida y tiene una respuesta aceptada. Además, puede ver cómo su respuesta contiene solo información ya mencionada en otras respuestas. La pregunta, al final, ya tiene 4 años. Proporcione orientación sobre las preguntas más recientes o sin respuesta. Gracias
Leonardfactory