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 forEach
metodo 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.