对于实现可迭代接口的对象,它必须实现指向返回[Symbol.iterator]
的函数的iterator
键。我想知道for..of
循环内部是否在对象上调用此方法来获取iterator
?
我很好奇的原因是,例如,Map
定义了一个带有多个迭代器(条目,值,键)的接口,如果没有明确指定for..of
循环,使用map.entries()
调用返回的迭代器。
我尝试搜索in the specification但它只指定将iterator
作为参数传递给抽象操作ForOf
:
使用参数调用抽象操作ForIn / OfBodyEvaluation lhs,stmt,迭代器,iterationKind,lhsKind和labelSet。
所以基本上有两个问题:
答案 0 :(得分:1)
指定操作的具体位置在7.4.1 GetIterator( obj [ , method ] )。这将获取步骤1a中传递的对象的@@iterator
属性。摘要操作:
一个。将方法设置为GetMethod( obj ,@@ iterator)。
@@iterator
是well-known symbol,是对象的Symbol.iterator
属性。
由于13.7.5.11 Runtime Semantics中的制作而由for-in和for-for循环使用:
IterationStatement :for(&em> AssignmentExpression 的 ForDeclaration )语句
- 让 keyResult 成为执行ForIn/OfHeadEvaluation( ForDeclaration 的绑定名称, AssignmentExpression ,迭代)的结果。
- 返回ForIn/OfBodyEvaluation( ForDeclaration , Statement , keyResult ,iterate,lexicalBinding, labelSet )
醇>
在这里,您可以看到传递给ForIn/OfBodyEvaluation的迭代器参数是ForIn/OfHeadEvaluation的返回值 keyResult 。在步骤7b中返回值:
湾返回GetIterator( exprValue )。
因此,for-of循环通过规范访问@@iterator
或Symbol.iterator
众所周知的符号来获取迭代器。
答案 1 :(得分:1)
对象只能定义一个符号Symbol.iterator
,这是在对象本身上迭代时调用的符号。
对象的其他属性(例如您给出的示例(entries
,keys
,values
)也可能返回迭代器,但这些迭代器通常不是相同的迭代器。他们可以相同,但这只是一个实现选择。在使用for..of
迭代对象时,调用迭代器没有任何歧义。这是[Symbol.iterator]
返回的那个。
- 如何从对象获取迭代器?
醇>
您可以通过调用Symbol.iterator
键入的功能来获取它,例如
const iterator = obj[Symbol.iterator]();
使用for..of
隐式检索它。
- 规范中指定了哪里?
醇>
@@ iterator" Symbol.iterator"
返回对象的默认Iterator的方法。由
for-of
语句的语义调用。
以下是如何创建自定义函数以返回对象的默认迭代器(覆盖默认迭代器),并查看它是如何被调用的:
const obj = {
// Define a custom function for returning the default iterator for this object
[Symbol.iterator]: function () {
console.log('The iterator-returning function got invoked');
// Return an iterator from some other object
// (but we could have created one from scratch as well):
return 'abc'[Symbol.iterator]();
},
myMethod: function () {
// This method happens to return the same iterator
return this[Symbol.iterator]();
},
myOtherMethod: function () {
// This method happens to return another iterator
return 'def'[Symbol.iterator]();
}
}
for (const a of obj) {
console.log(a); // a b c
}
for (const a of obj.myMethod()) {
console.log(a); // a b c
}
for (const a of obj.myOtherMethod()) {
console.log(a); // d e f
}

.as-console-wrapper { max-height: 100% !important; top: 0; }