为什么对象默认情况下不可迭代?
我经常看到与迭代对象相关的问题,常见的解决方案是迭代对象的属性并以这种方式访问对象中的值。这似乎很常见,这让我想知道为什么对象本身不可迭代。
像 ES6 中的 for...of
这样的语句默认情况下不支持对象,只适用于特殊“可迭代对象”,而 {}
对象不在其中,因此我们必须费尽周折才能使其适用于我们想要使用它的对象。
for...of 语句创建一个循环,用于迭代可迭代对象(包括数组、映射、集合、参数对象等)...
例如,使用 ES6 的 生成器函数:
var example = {a: {e: 'one', f: 'two'}, b: {g: 'three'}, c: {h: 'four', i: 'five'}};
function* entries(obj) {
for (let key of Object.keys(obj)) {
yield [key, obj[key]];
}
}
for (let [key, value] of entries(example)) {
console.log(key);
console.log(value);
for (let [key, value] of entries(value)) {
console.log(key);
console.log(value);
}
}
当我在支持ES6的Firefox中运行代码时,以上内容能够按照我期望的顺序正确记录数据:
默认情况下,{}
对象不可迭代,但为什么?对象可迭代的潜在好处是否会被劣势所超越?与此相关的问题是什么?
另外,由于{}
对象与“类数组”集合和“可迭代对象”(例如NodeList
、HtmlCollection
和arguments
)不同,它们不能被转换为数组。
例如:
var argumentsArray = Array.prototype.slice.call(arguments);
或者使用数组方法:
Array.prototype.forEach.call(nodeList, function (element) {})
。
除了上面提到的问题,我还想看到一个可以使{}
对象变成可迭代的工作示例,特别是那些提到[Symbol.iterator]
的人。这应该允许这些新的{}
“可迭代对象”使用像for...of
这样的语句。此外,我想知道使对象可迭代是否允许将它们转换为数组。
我尝试了下面的代码,但是我得到了一个TypeError:无法将未定义转换为对象
。
var example = {a: {e: 'one', f: 'two'}, b: {g: 'three'}, c: {h: 'four', i: 'five'}};
// I want to be able to use "for...of" for the "example" object.
// I also want to be able to convert the "example" object into an Array.
example[Symbol.iterator] = function* (obj) {
for (let key of Object.keys(obj)) {
yield [key, obj[key]];
}
};
for (let [key, value] of example) { console.log(value); } // error
console.log([...example]); // error
Symbol.iterator
属性的对象都是可迭代的。因此,您只需要实现该属性即可。为什么对象不可迭代的一个可能的解释是,这将意味着一切都是可迭代的,因为一切都是对象(当然除了原始类型)。但是,遍历函数或正则表达式对象意味着什么? - Felix Kling