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


112

Oltre alla migliore leggibilità, c'è qualche vantaggio includesnell'over indexOf? Mi sembrano identici.

Qual è la differenza tra this

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

E questo?

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

12
includesha un supporto browser molto peggiore.
Quentin

4
Nota che includesnon fa parte di ES6 / ES2015. È una proposta per la prossima versione di ECMAScript e sarà aggiunta quest'anno.
Felix Kling

4
Volevo solo menzionare che includesNON è affatto supportato in IE
ZvKa

Risposte:


138

tl; dr: NaN viene trattato in modo diverso:

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

Dalla proposta :

Motivazione

Quando si utilizzano gli array ECMAScript, è generalmente opportuno determinare se l'array include un elemento. Il modello prevalente per questo è

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

con varie altre possibilità, ad esempio arr.indexOf(el) >= 0o anche ~arr.indexOf(el).

Questi modelli presentano due problemi:

  • Non riescono a "dire quello che vuoi dire": invece di chiedere se l'array include un elemento, chiedi qual è l'indice della prima occorrenza di quell'elemento nell'array, e poi lo confronti o lo modifichi per determinare la risposta alla tua vera domanda.
  • Non riescono NaN, poiché indexOfutilizza Strict Equality Comparison e quindi [NaN].indexOf(NaN) === -1.

La soluzione proposta

Proponiamo l'aggiunta di un Array.prototype.includesmetodo, in modo tale che i modelli di cui sopra possono essere riscritti come

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

Questo ha quasi la stessa semantica del precedente, tranne per il fatto che utilizza l'algoritmo di confronto SameValueZero invece di Strict Equality Comparison, rendendolo così [NaN].includes(NaN)vero.

Pertanto, questa proposta risolve entrambi i problemi visti nel codice esistente.

Aggiungiamo inoltre un fromIndexparametro, simile a Array.prototype.indexOfe String.prototype.includes, per coerenza.


Ulteriori informazioni:


1
Solo metà della verità. Anche diverso: gli elementi mancanti sono trattati come undefinedda .includes()e non sono considerati da .indexOf().
Robert Siemer

11

Se ti chiedi quali siano le prestazioni, per il momento indexOf è più veloce, ma questo test JSperf tende a mostrare che più passa il tempo, più includes()sarà più veloce di indexOf(immagino che sarà ottimizzato ulteriormente).

IMHO, anche io preferisco scrivere if (arr.includes(el)) {}poiché è più chiaro e più gestibile diif (arr.indexOf(el) !== -1) {}


1
Sembra che la differenza di prestazioni non sia così ovvia. Il mio Firefox mobile mostra che indexOf è effettivamente più veloce. Alcune versioni di Chrome si comportano allo stesso modo ... Ma la differenza sembra comunque trascurabile nelle implementazioni odierne.
Nux

8

.indexOf()e .includes()metodi possono essere usati per cercare un elemento in un array o per cercare un carattere / sottostringa in una data stringa.

Utilizzo in Array

( Collegamento alla specifica ECMAScript)

  1. indexOfutilizza Strict Equality Comparison mentre includesutilizza l' algoritmo SameValueZero . Per questo motivo, sorgono i seguenti due punti di differenza.

  2. Come sottolineato da Felix Kling , il comportamento è diverso in caso di NaN.

let arr = [NaN];

arr.indexOf(NaN); // returns -1; meaning NaN is not present
arr.includes(NaN); // returns true
  1. Il comportamento è diverso anche in caso di undefined.
let arr = [ , , ];

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

Utilizzo in String

( Collegamento alla specifica ECMAScript)

  1. Se passi una RegExp a indexOf, tratterà la RegExp come una stringa e restituirà l'indice della stringa, se trovato. Tuttavia, se passi una RegExp a includes, verrà generata un'eccezione.
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

Prestazione

Come ha sottolineato 538ROMEO , includespotrebbe essere un po '(molto piccolo) un po' più lento (poiché deve controllare una regex come primo argomento) rispetto indexOfma in realtà, questo non fa molta differenza ed è trascurabile.

Storia

String.prototype.includes()è stato introdotto in ECMAScript 2015 mentre è Array.prototype.includes()stato introdotto in ECMAScript 2016. Per quanto riguarda il supporto del browser, usali con saggezza.

String.prototype.indexOf()e Array.prototype.indexOf()sono presenti nell'edizione ES5 di ECMAScript e quindi supportati da tutti i browser.


indexOftruedopo aver impostato esplicitamente undefinedun array: let arr=[undefined];o let arr=[];arr[0]=undefined;Nowarr.indexOf(undefined) === 0
Jay Dadhania

Sei l'unico che indica la differenza con undefined: Il motivo è che .includestratta gli elementi mancanti come undefined, mentre .indexOf()li ignora. Puoi anche "creare" elementi mancanti con arr[number beyond length] = whatever.
Robert Siemer

Nessuno chiedeva stringhe, ma le tue osservazioni suggeriscono che .includes()mangia solo stringhe. In realtà entrambi i metodi costringono qualsiasi cosa a una stringa nel miglior modo possibile. Regex è specificamente escluso come argomento .includes()per permettere future aggiunte allo standard secondo il progetto in corso.
Robert Siemer

4

Concettualmente dovresti usare indexOf quando vuoi usare la posizione indexOf ti da solo per estrarre il valore o operare sull'array, cioè usando slice, shift o split dopo aver ottenuto la posizione dell'elemento. D'altra parte, Usa Array.include solo per sapere se il valore è all'interno dell'array e non la posizione perché non ti interessa.


0

indexOf()e includes()possono essere utilizzati entrambi per trovare elementi in un array, tuttavia ogni funzione restituisce valori di ritorno diversi.

indexOfrestituisce un numero ( -1se l'elemento non è presente nell'array, o la posizione dell'array se l'elemento è presente).

includes()restituisce un valore booleano ( trueo false).


Ciao Kruti, questa domanda ha già ricevuto una risposta e ha una risposta accettata. Inoltre, puoi vedere come la tua risposta contiene solo informazioni già dette in altre risposte. La domanda, alla fine, ha già 4 anni. Fornisci indicazioni sulle domande più recenti o su quelle senza risposta. Grazie
Leonardfactory
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.