1. Kompatybilność wsteczna
JavaScript jest implementacją ECMAScript . Większość tych funkcji została wprowadzona w ECMAScript 5 (ES5), jednak wiele starszych przeglądarek, które nadal mają wystarczająco duży udział w rynku, nie obsługuje tych funkcji (patrz tabela kompatybilności ECMAScript 5 ), z których najbardziej godne uwagi jest IE8.
Zasadniczo biblioteki powrócą do implementacji natywnej, jeśli istnieje, w przeciwnym razie użyj własnego wypełniania, na przykład spójrzmy na implementację 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;
}
Poniższe wiersze sprawdzają, czy forEach
metoda istnieje na obiekcie i czy jest to wersja AngularJS, czy nie. Jeśli nie, używa już określonej funkcji (wersja natywna):
} else if (obj.forEach && obj.forEach !== forEach) {
obj.forEach(iterator, context);
}
2. Wygoda
W natywnym JavaScript Array.prototype.forEach
jest metodą wyłączną dla instancji Array
, jednak większość z nich Object
jest również iterowalna.
Z tego powodu wielu twórców bibliotek uczyniło swoje funkcje polimorficznymi (zdolnymi do przyjmowania wielu typów jako danych wejściowych). Weźmy powyżej kod AngularJS i zobaczmy, jakie dane wejściowe akceptuje:
Funkcje :
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);
}
}
Tablice (z natywną obsługą forEach):
} else if (obj.forEach && obj.forEach !== forEach) {
obj.forEach(iterator, context);
Obiekty podobne do tablicy, w tym Array (bez natywnej obsługi forEach), String, HTMLElement, Object z prawidłową właściwością length:
} else if (isArrayLike(obj)) {
for (key = 0; key < obj.length; key++)
iterator.call(context, obj[key], key);
Obiekty:
} else {
for (key in obj) {
if (obj.hasOwnProperty(key)) {
iterator.call(context, obj[key], key);
}
}
}
Wniosek
Jak widać, AngularJS będzie iterował większość obiektów JavaScript, chociaż działa w taki sam sposób, jak natywna funkcja, akceptuje znacznie więcej różnych typów danych wejściowych, a zatem jest ważnym dodatkiem do biblioteki, a także sposobem na wprowadzenie funkcji ES5 do starszych przeglądarek.