EcmaScript 6
Se stai usando ES6, puoi costruire un array di elementi e usare includes
:
['a', 'b', 'c'].includes('b')
Ciò ha alcuni vantaggi intrinseci indexOf
perché può testare correttamente la presenza di NaN
nell'elenco e può abbinare elementi di array mancanti come quello centrale [1, , 2]
a undefined
. includes
funziona anche su matrici tipizzate JavaScript come Uint8Array
.
Se sei preoccupato per il supporto del browser (come per IE o Edge), puoi controllare Array.includes
su CanIUse.Com e se desideri scegliere come target un browser o una versione del browser mancante includes
, ti consiglio polyfill.io per il polyfilling.
Senza matrice
È possibile aggiungere una nuova isInList
proprietà alle stringhe come segue:
if (!String.prototype.isInList) {
String.prototype.isInList = function() {
let value = this.valueOf();
for (let i = 0, l = arguments.length; i < l; i += 1) {
if (arguments[i] === value) return true;
}
return false;
}
}
Quindi usalo così:
'fox'.isInList('weasel', 'fox', 'stoat') // true
'fox'.isInList('weasel', 'stoat') // false
Puoi fare la stessa cosa per Number.prototype
.
Array.indexOf
Se stai utilizzando un browser moderno, indexOf
funziona sempre. Tuttavia, per IE8 e versioni precedenti è necessario un polyfill.
Se indexOf
restituisce -1, l'elemento non è nell'elenco. Tuttavia, tieni presente che questo metodo non controlla correttamente NaN
e, sebbene possa corrispondere a un esplicito undefined
, non può corrispondere a un elemento mancante undefined
come nell'array [1, , 2]
.
Polyfill per indexOf
o includes
in IE o qualsiasi altro browser / versione privo di supporto
Se non si desidera utilizzare un servizio come polyfill.io come menzionato sopra, è sempre possibile includere i propri polyfill personalizzati conformi agli standard del codice sorgente. Ad esempio, Mozilla Developer Network ne ha uno per indexOf
.
In questa situazione in cui dovevo creare una soluzione per Internet Explorer 7, ho "lanciato la mia" versione più semplice della indexOf()
funzione che non è conforme agli standard:
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function(item) {
var i = this.length;
while (i--) {
if (this[i] === item) return i;
}
return -1;
}
}
Tuttavia, non penso che la modifica Array.prototype
sia la migliore risposta a lungo termine. La modifica Object
e i Array
prototipi in JavaScript possono portare a gravi bug. Devi decidere se farlo è sicuro nel tuo ambiente. La nota principale è che iterando un array (quando Array.prototype ha aggiunto proprietà) for ... in
restituirà il nuovo nome della funzione come uno dei tasti:
Array.prototype.blah = function() { console.log('blah'); };
let arr = [1, 2, 3];
for (let x in arr) { console.log(x); }
// Result:
0
1
2
blah // Extra member iterated over!
Il tuo codice potrebbe funzionare ora, ma nel momento in cui qualcuno in futuro aggiungerà una libreria o plugin JavaScript di terze parti che non protegge con zelo dalle chiavi ereditate, tutto può rompersi.
Il vecchio modo per evitare tale rottura è, durante l'enumerazione, verificare ogni valore per vedere se l'oggetto ha effettivamente come proprietà non ereditata if (arr.hasOwnProperty(x))
e solo allora lavorare con quello x
.
Il nuovo modo ES6 per evitare questo problema extra-chiave è di usare of
al posto di in
, for (let x of arr)
. Tuttavia, a meno che tu non possa garantire che tutto il tuo codice e le librerie di terze parti si attengano rigorosamente a questo metodo, quindi ai fini di questa domanda probabilmente vorrai semplicemente usare includes
come sopra indicato.