1.向后兼容
JavaScript是ECMAScript的实现。这些功能大多数是在ECMAScript 5(ES5)中引入的,但是,许多仍然占有相当大市场份额的较旧的浏览器不支持这些功能(请参阅ECMAScript 5兼容性表),其中最著名的是IE8。
通常,如果存在库,则库将还原为本机实现,否则使用其自己的polyfill,例如,让我们看一下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;
}
以下几行检查该forEach
方法是否存在于对象上以及它是否为AngularJS版本。如果不是,它将使用已经指定的功能(本机版本):
} else if (obj.forEach && obj.forEach !== forEach) {
obj.forEach(iterator, context);
}
2.便利
在本机JavaScript中,Array.prototype.forEach
是的实例专有的方法Array
,但是大多数方法Object
也是可迭代的。
因此,许多库创建者使它们的函数成为多态的(能够接受多种类型作为输入)。让我们看一下上面的AngularJS代码,看看它接受什么输入:
功能:
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);
}
}
数组(具有原生forEach支持):
} else if (obj.forEach && obj.forEach !== forEach) {
obj.forEach(iterator, context);
类似于数组的对象,包括数组(不支持本地forEach),字符串,HTMLElement和具有有效length属性的对象:
} 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);
}
}
}
结论
如您所见,AngularJS会迭代大多数JavaScript对象,尽管它的工作方式与本机函数相同,但它接受的输入类型要多得多,因此是对库的有效补充,也是带来ES5函数的一种方式到旧版浏览器。