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 cuota de mercado suficientemente significativa no admiten estas funciones (consulte tabla de compatibilidad ECMAScript 5 ), el más notable de estos es IE8.
En general, las bibliotecas volverán a la implementación nativa si existe, de lo contrario usarán 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 comprueban si el método forEach
existe en el objeto y si es la versión de AngularJS o no. Si no usa 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, casi cualquier Object
también es iterable.
Por esta razón, muchos creadores de bibliotecas realizan sus funciones polymorphic (capaz de aceptar múltiples tipos como entrada) . Tomemos el código AngularJS de arriba 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);
}
}
Arrays (con soporte nativo de forEach):
} else if (obj.forEach && obj.forEach !== forEach) {
obj.forEach(iterator, context);
Objetos similares a una matriz que incluyen una matriz (sin soporte nativo para cada uno), Cadena, HTMLElement, Objeto 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 tipos de entrada mucho más diferentes y, por lo tanto, es una adición válida a la biblioteca, así como una forma de llevando las funciones de ES5 a los navegadores heredados.