Array.prototype.includes vs. Array.prototype.indexOf

112

Além da legibilidade aprimorada, há alguma vantagem em includesmais indexOf? Eles parecem idênticos para mim.

Qual é a diferença entre isso

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

E isto?

var y = [1,2,3].includes(1); //true
Matt
fonte
12
includestem suporte de navegador muito pior.
Quentin de
4
Observe que includesnão faz parte do ES6 / ES2015. É uma proposta para a próxima versão do ECMAScript e será adicionada este ano.
Felix Kling
4
só queria mencionar também que includesNÃO é suportado no IE
ZvKa

Respostas:

138

tl; dr: NaN é tratado de forma diferente:

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

Da proposta :

Motivação

Ao usar matrizes ECMAScript, geralmente é desejável determinar se a matriz inclui um elemento. O padrão predominante para isso é

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

com várias outras possibilidades, por exemplo arr.indexOf(el) >= 0, ou mesmo ~arr.indexOf(el).

Esses padrões apresentam dois problemas:

  • Eles falham em "dizer o que você quer dizer": em vez de perguntar se a matriz inclui um elemento, você pergunta qual é o índice da primeira ocorrência desse elemento na matriz e, em seguida, o compara ou faz uma pequena variação para determinar a resposta à sua pergunta real.
  • Eles falham NaN, como indexOfusa a Comparação Estrita de Igualdade e assim [NaN].indexOf(NaN) === -1.

Solução proposta

Propomos a adição de um Array.prototype.includesmétodo, de modo que os padrões acima possam ser reescritos como

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

Isso tem quase a mesma semântica que o anterior, exceto que usa o algoritmo de comparação SameValueZero em vez da comparação estrita de igualdade, tornando-se assim [NaN].includes(NaN)verdadeiro.

Assim, esta proposta resolve os dois problemas vistos no código existente.

Além disso, adicionamos um fromIndexparâmetro, semelhante a Array.prototype.indexOfe String.prototype.includes, para consistência.


Outras informações:

Felix Kling
fonte
1
Apenas meia verdade. Também diferente: os elementos ausentes são tratados como undefinedpor .includes()e não são considerados por .indexOf().
Robert Siemer,
11

Se você está se perguntando sobre o desempenho, por enquanto, indexOf é mais rápido, mas esse teste JSperf tende a mostrar que quanto mais o tempo passa, mais includes()será mais rápido do que indexOf(acho que será otimizado ainda mais).

IMHO, também prefiro escrever, if (arr.includes(el)) {}pois é mais claro e mais fácil de manter do queif (arr.indexOf(el) !== -1) {}

538ROMEO
fonte
1
Parece que a diferença de desempenho não é tão óbvia. Meu Firefox móvel mostra que indexOf é realmente mais rápido. Algumas versões do Chrome agem da mesma forma ... Mas a diferença parece insignificante de qualquer maneira nas implementações de hoje.
Nux
8

.indexOf()e os .includes()métodos podem ser usados ​​para pesquisar um elemento em uma matriz ou para pesquisar um caractere / substring em uma determinada string.

Uso em matriz

( Link para a Especificação ECMAScript)

  1. indexOfusa comparação de igualdade estrita enquanto includesusa o algoritmo SameValueZero . Por esse motivo, surgem os dois pontos de diferenças a seguir.

  2. Conforme apontado por Felix Kling , o comportamento é diferente no caso de NaN.

let arr = [NaN];

arr.indexOf(NaN); // returns -1; meaning NaN is not present
arr.includes(NaN); // returns true
  1. O comportamento também é diferente no caso de undefined.
let arr = [ , , ];

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

Uso em String

( Link para a Especificação ECMAScript)

  1. Se você passar um RegExp para indexOf, ele tratará o RegExp como uma string e retornará o índice da string, se encontrado. No entanto, se você passar um RegExp para includes, ele lançará uma exceção.
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

atuação

Como 538ROMEO apontou, includespode ser um pouco (muito pequeno) um pouco mais lento (pois ele precisa verificar se há um regex como o primeiro argumento) do que, indexOfmas na realidade, isso não faz muita diferença e é insignificante.

História

String.prototype.includes()foi introduzido no ECMAScript 2015 enquanto Array.prototype.includes()foi introduzido no ECMAScript 2016. Com relação ao suporte do navegador, use-os com sabedoria.

String.prototype.indexOf()e Array.prototype.indexOf()estão presentes na edição ES5 do ECMAScript e, portanto, são suportados por todos os navegadores.

Srishti
fonte
indexOftruedepois de definir explicitamente undefinedem uma matriz: let arr=[undefined];ou let arr=[];arr[0]=undefined;Agoraarr.indexOf(undefined) === 0
Jay Dadhania
Você é o único que indica a diferença com undefined: O motivo é que .includestrata os elementos ausentes como undefined, enquanto os .indexOf()ignora. Você também pode “criar” elementos ausentes com arr[number beyond length] = whatever.
Robert Siemer
Ninguém estava pedindo cordas, mas seus comentários sugerem que .includes()só come cordas. Na realidade, ambos os métodos coagem qualquer coisa a uma string tão boa quanto possível. Regex é especificamente excluído como argumento para .includes()a permitir futuras adições para o padrão de acordo com o projecto actual.
Robert Siemer
4

Conceitualmente, você deve usar indexOf quando quiser usar a posição indexOf, apenas para extrair o valor ou operar sobre o array, ou seja, usando slice, shift ou split após obter a posição do elemento. Por outro lado, Use Array.includes apenas para saber se o valor está dentro da matriz e não a posição, porque você não se importa com isso.

Sebastian gomez
fonte
0

indexOf()e includes()podem ser usados ​​para localizar elementos em uma matriz, no entanto, cada função produz valores de retorno diferentes.

indexOfretorna um número ( -1se o elemento não estiver presente na matriz, ou a posição da matriz se o elemento estiver presente).

includes()retorna um valor booleano ( trueou false).

Kruti
fonte
Olá Kruti, esta questão já foi respondida e tem uma resposta aceita. Além disso, você pode ver como sua resposta contém apenas informações já ditas em outras respostas. A questão, no final, já tem 4 anos. Forneça orientação sobre as perguntas mais recentes ou não respondidas. Obrigado
leonardfactory