1. Compatibilidad con versiones anteriores
JavaScript es una implementación de ECMAScript . La mayoría de esas funciones se introdujeron en ECMAScript 5 (ES5), sin embargo, muchos navegadores antiguos que todavía tienen una participación lo suficientemente significativa en el mercado no son compatibles con estas funciones (consulte la tabla de compatibilidad de ECMAScript 5 ), la más notable de ellas es IE8.
En general, las bibliotecas volverán a la implementación nativa si existe; de lo contrario, use su propio polyfill, por ejemplo, veamos la implementación de 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;
}
Las siguientes líneas verifican si el forEach
método existe en el objeto y si es la versión AngularJS o no. Si no, utiliza la función ya especificada (la versión nativa):
} else if (obj.forEach && obj.forEach !== forEach) {
obj.forEach(iterator, context);
}
2. Conveniencia
En JavaScript nativo Array.prototype.forEach
es un método exclusivo de una instancia de Array
, sin embargo, la mayoría de cualquiera Object
es iterable también.
Por esta razón, muchos creadores de bibliotecas hacen que sus funciones sean polimórficas (capaces de aceptar múltiples tipos como entrada). Tomemos el código AngularJS anterior y veamos qué entradas acepta:
Funciones :
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);
}
}
Matrices (con soporte nativo para cada uno):
} else if (obj.forEach && obj.forEach !== forEach) {
obj.forEach(iterator, context);
Objetos de tipo Array, incluidos Array (sin soporte nativo para cada uno), String, HTMLElement, Object con una propiedad de longitud válida:
} else if (isArrayLike(obj)) {
for (key = 0; key < obj.length; key++)
iterator.call(context, obj[key], key);
Objetos:
} else {
for (key in obj) {
if (obj.hasOwnProperty(key)) {
iterator.call(context, obj[key], key);
}
}
}
Conclusión
Como puede ver, AngularJS iterará sobre la mayoría de los objetos JavaScript, aunque funciona de la misma manera que la función nativa, acepta muchos más tipos diferentes de entrada y, por lo tanto, es una adición válida a la biblioteca y una forma de traer funciones ES5 a navegadores heredados.