我在 Javascript: The Good Parts 上阅读...
由于 JavaScript 的数组实际上是对象,因此该
for in
语句可用于遍历数组的所有属性。不幸的是,因为 in 不能保证属性的顺序......
据我所知,“每个”函数都基于for in
,那么each
函数形式的 JQuery 和 Underscore 库在遍历数组时是否保证顺序?我试图避免烦人的标准for
。
先感谢您。
我在 Javascript: The Good Parts 上阅读...
由于 JavaScript 的数组实际上是对象,因此该
for in
语句可用于遍历数组的所有属性。不幸的是,因为 in 不能保证属性的顺序......
据我所知,“每个”函数都基于for in
,那么each
函数形式的 JQuery 和 Underscore 库在遍历数组时是否保证顺序?我试图避免烦人的标准for
。
先感谢您。
遍历数组时,始终保证顺序。当您遍历(非数组)对象时,就无法保证。顺便说一下,数组仍然是对象。
each
只不过是for in
用于对象和for
类似数组的。框架确定了作业的正确循环,并且适用相同的逻辑:数组迭代是有序的,而对象迭代不是。
下划线的来源:
var each = _.each = _.forEach = function (obj, iterator, context) {
if (obj == null) return;
if (nativeForEach && obj.forEach === nativeForEach) {
obj.forEach(iterator, context);
} else if (obj.length === +obj.length) {
for (var i = 0, l = obj.length; i < l; i++) {
if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return;
}
} else {
for (var key in obj) {
if (_.has(obj, key)) {
if (iterator.call(context, obj[key], key, obj) === breaker) return;
}
}
}
};
jQuery的来源:
each: function (object, callback, args) {
var name, i = 0,
length = object.length,
isObj = length === undefined || jQuery.isFunction(object);
if (args) {
if (isObj) {
for (name in object) {
if (callback.apply(object[name], args) === false) {
break;
}
}
} else {
for (; i < length;) {
if (callback.apply(object[i++], args) === false) {
break;
}
}
}
// A special, fast, case for the most common use of each
} else {
if (isObj) {
for (name in object) {
if (callback.call(object[name], name, object[name]) === false) {
break;
}
}
} else {
for (; i < length;) {
if (callback.call(object[i], i, object[i++]) === false) {
break;
}
}
}
}
return object;
}
有两种方法可以遍历数组:对数组的索引元素进行数值循环,或者对数组的对象属性for in
进行循环。
var a = ['a','b'];
a[3] = 'e';
a[2] = 'd';
a.foo = function() { };
for(key in a)
console.log(key);
这将返回0 1 3 2 foo
,因为这是定义属性的顺序(但也不能保证您的浏览器甚至需要表现出这种行为)。
到目前为止,数值循环看起来更好,但它们不能处理备用数组,即有间隙的数组。ES5Array.forEach
省略了未指定的值,而 jQuery$.each
使用基于length
属性的数字循环。
var a = [1,2];
a[1000000] = 4;
a[9000] = 3;
a.foo = function() {};
// outputs 0, 1, 9000, 1000000 -- note they are in order
a.forEach(function(elem, index){ console.log(index); })
// outputs 0, 1, 9000, 1000000 -- same as above
_.each(a, function(elem, index){ console.log(index); })
// outputs a million values and locks up your browser for a while
$.each(a, function(index){ console.log(index); })
因此,两者都forEach
以$.each
索引顺序返回您的值,但forEach
Underscore 对于稀疏数组似乎更胜一筹,因为它们忽略了尚未分配给它们的值的索引。