1. Compatibilità con le versioni precedenti
JavaScript è un'implementazione di ECMAScript . La maggior parte di queste funzioni sono state introdotte in ECMAScript 5 (ES5), tuttavia molti browser meno recenti che hanno ancora una quota abbastanza significativa del mercato non supportano queste funzioni (vedere la tabella di compatibilità di ECMAScript 5 ), il più notevole di questi è IE8.
Generalmente le librerie torneranno all'implementazione nativa se esiste, altrimenti usano il proprio polyfill, per esempio diamo un'occhiata all'implementazione di AngularJS ( angular.js L203-257 ):
function forEach(obj, iterator, context) {
var key;
if (obj) {
if (isFunction(obj)){
for (key in obj) {
// Need to check if hasOwnProperty exists,
// as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function
if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) {
iterator.call(context, obj[key], key);
}
}
} else if (obj.forEach && obj.forEach !== forEach) {
obj.forEach(iterator, context);
} else if (isArrayLike(obj)) {
for (key = 0; key < obj.length; key++)
iterator.call(context, obj[key], key);
} else {
for (key in obj) {
if (obj.hasOwnProperty(key)) {
iterator.call(context, obj[key], key);
}
}
}
}
return obj;
}
Le seguenti righe verificano se il forEachmetodo esiste sull'oggetto e se è la versione di AngularJS o meno. In caso contrario utilizza la funzione già specificata (la versione nativa):
} else if (obj.forEach && obj.forEach !== forEach) {
obj.forEach(iterator, context);
}
2. Convenienza
In JavaScript nativo Array.prototype.forEachè un metodo esclusivo di un'istanza di Array, tuttavia la maggior parte Objectè anche iterabile.
Per questo motivo molti creatori di librerie rendono polimorfiche le loro funzioni (in grado di accettare più tipi come input). Prendiamo il codice AngularJS sopra e vediamo quali input accetta:
Funzioni :
if (isFunction(obj)){
for (key in obj) {
// Need to check if hasOwnProperty exists,
// as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function
if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) {
iterator.call(context, obj[key], key);
}
}
Array (con supporto nativo per ogni supporto):
} else if (obj.forEach && obj.forEach !== forEach) {
obj.forEach(iterator, context);
Oggetti simili a array tra cui Array (senza supporto forEach nativo), String, HTMLElement, Object con proprietà lunghezza valida:
} else if (isArrayLike(obj)) {
for (key = 0; key < obj.length; key++)
iterator.call(context, obj[key], key);
Oggetti:
} else {
for (key in obj) {
if (obj.hasOwnProperty(key)) {
iterator.call(context, obj[key], key);
}
}
}
Conclusione
Come puoi vedere AngularJS eseguirà l'iterazione su quasi tutti gli oggetti JavaScript, anche se funziona allo stesso modo della funzione nativa, accetta tipi di input molto più diversi e quindi è una valida aggiunta alla libreria e un modo per portare le funzioni ES5 ai browser legacy.