for..in 循环是否跟踪对象的属性顺序?
Does for..in loop keeps track of orders of its properties for Object?
我是编程的初学者,JavaScript 是我的第一语言。我在读书的时候遇到了这个顾虑,不知道自己的顾虑对不对。
我认为 for..in
当我们循环遍历对象时,循环不会跟踪顺序,因为与数组不同,对象的属性不是基于索引的。
这让我质疑我从 Underscore.js 重新创建一些方法的工作,例如 _.each
和 _.reduce
以下是我重新创建这些方法的尝试。
var each = function(list, iteratee) {
if (Array.isArray(list)) {
for (var i = 0; i < list.length; i++) {
iteratee(list[i], i, list);
}
} else if (list.constructor === Object) {
for (var key in list) {
iteratee(list[key], key, list);
}
}
};
var reduce = function(list, iteratee, memo){
var memoUndefined = arguments.length < 3;
each(list, function(elem, index, list){
if (memoUndefined) {
memoUndefined = false;
memo = elem;
} else {
memo = iteratee(memo, elem, index, list);
}
});
return memo;
};
它们似乎可以正常工作,因此可以像 list
一样在 Array 和 Object 上工作,无论是否提供 memo
。
但是,让我感到疑惑的是,我的 each
函数如何跟踪它正在迭代的属性的顺序?它如何确保被循环的属性的顺序始终一致?它对数组有意义,因为它的属性是索引。但对象不是。我相信这在像我上面的 reduce
这样的函数中实现时可能会有潜在的问题。如果 iteratee
将来做的只是简单的加法或减法,那可能没问题,但是乘法或除法呢?值 each
将迭代的顺序将是至关重要的。我的担心合适吗?
ECMAScript ES5 规范特别指出 for/in
循环不保证属性的顺序。来自 ES5 规范中的section 12.6.4:
The mechanics and order of enumerating the properties (step 6.a in the
first algorithm, step 7.a in the second) is not specified.
不过,在大多数 ES5 浏览器实现中,属性是按照它们创建的顺序迭代的。
我读到有人建议将 for/in 的属性顺序记录为新兴 ES6 规范中创建的顺序。
我在ES6草案中没有找到这个具体的写法,但是有关于Object.keys()
的注释:
If an implementation defines a specific order of enumeration for the
for-in statement, the same order must be used for the elements of the
array returned in step 4.
请记住,即使顺序始终是特定方式,也没有修改顺序的功能。因此,如果您真的关心属性的顺序,那么对象上的 for/in
循环可能并不是 store/access 一组有序属性的正确方法。
我是编程的初学者,JavaScript 是我的第一语言。我在读书的时候遇到了这个顾虑,不知道自己的顾虑对不对。
我认为 for..in
当我们循环遍历对象时,循环不会跟踪顺序,因为与数组不同,对象的属性不是基于索引的。
这让我质疑我从 Underscore.js 重新创建一些方法的工作,例如 _.each
和 _.reduce
以下是我重新创建这些方法的尝试。
var each = function(list, iteratee) {
if (Array.isArray(list)) {
for (var i = 0; i < list.length; i++) {
iteratee(list[i], i, list);
}
} else if (list.constructor === Object) {
for (var key in list) {
iteratee(list[key], key, list);
}
}
};
var reduce = function(list, iteratee, memo){
var memoUndefined = arguments.length < 3;
each(list, function(elem, index, list){
if (memoUndefined) {
memoUndefined = false;
memo = elem;
} else {
memo = iteratee(memo, elem, index, list);
}
});
return memo;
};
它们似乎可以正常工作,因此可以像 list
一样在 Array 和 Object 上工作,无论是否提供 memo
。
但是,让我感到疑惑的是,我的 each
函数如何跟踪它正在迭代的属性的顺序?它如何确保被循环的属性的顺序始终一致?它对数组有意义,因为它的属性是索引。但对象不是。我相信这在像我上面的 reduce
这样的函数中实现时可能会有潜在的问题。如果 iteratee
将来做的只是简单的加法或减法,那可能没问题,但是乘法或除法呢?值 each
将迭代的顺序将是至关重要的。我的担心合适吗?
ECMAScript ES5 规范特别指出 for/in
循环不保证属性的顺序。来自 ES5 规范中的section 12.6.4:
The mechanics and order of enumerating the properties (step 6.a in the first algorithm, step 7.a in the second) is not specified.
不过,在大多数 ES5 浏览器实现中,属性是按照它们创建的顺序迭代的。
我读到有人建议将 for/in 的属性顺序记录为新兴 ES6 规范中创建的顺序。
我在ES6草案中没有找到这个具体的写法,但是有关于Object.keys()
的注释:
If an implementation defines a specific order of enumeration for the for-in statement, the same order must be used for the elements of the array returned in step 4.
请记住,即使顺序始终是特定方式,也没有修改顺序的功能。因此,如果您真的关心属性的顺序,那么对象上的 for/in
循环可能并不是 store/access 一组有序属性的正确方法。