javascript - 在 JavaScript ES6 中,调用 iterable[Symbol.iterator] 时将 `this` 绑定到 iterable,但 Mozilla 和 ES6 规范都没有提到它?
问题描述
目前,Mozilla 规范和ES6 规范都提到了 iterableobj
的含义如下:
obj[Symbol.iterator]
应该引用一个零参数函数,这样当被调用时,应该返回一个符合迭代器协议的对象
但是他们都没有提到这个函数实际上是在obj
自身上调用的。
这可能很重要,因为我刚刚看到了这样的用法:
const aClass = {
teacher: "Mary",
students: ["Peter", "Michael"],
location: "Room 123, Building One",
[Symbol.iterator]: function* () {
yield this.teacher;
for (const student of this.students) {
yield student;
}
}
};
for (const member of aClass) console.log(member);
console.log([...aClass]);
请注意,老师和两个学生都被打印出来了。
所以这个[Symbol.iterator]
协议就像:给这个对象的用户一种迭代我的方式,以我指定的方式。
所以 Mozilla 和 ES6 的规范真的应该提到这个函数是在可迭代对象上调用的,还是this
绑定到可迭代对象?
(或者也许 ES6 实现规范提到了它......但我认为接口应该告诉所有关于它是如何使用的,并且不应该要求用户也阅读实现)。
解决方案
您可以以编程方式使用您想要.call
的[Symbol.iterator]
任何值:this
const aClass = {
teacher: "Mary",
students: ["Peter", "Michael"],
location: "Room 123, Building One",
[Symbol.iterator]: function* () {
yield this.teacher;
for (const student of this.students) {
yield student;
}
}
};
const iterator = aClass[Symbol.iterator].call({ foo: null });
console.log(iterator.next());
console.log(iterator.next());
但是对于这种情况,您通过调用迭代器
console.log([...aClass]);
它执行(除其他外)ArrayAccumulation中描述的步骤:
SpreadElement : ... AssignmentExpression
1. Let spreadRef be the result of evaluating AssignmentExpression.
2. Let spreadObj be GetValue(spreadRef).
3. Let iterator be GetIterator(spreadObj).
4. ReturnIfAbrupt(iterator).
5. Repeat (iterate over iterator, assign properties to the array being created)
看看GetIterator
:
a. Let method be GetMethod(obj, @@iterator).
...
3. Let iterator be Call(method,obj).
第一个参数在哪里obj
传递(对于ArrayAccumulation
,它是spreadObj
)。
Call
它使用第二个参数的调用上下文 (a this
)调用作为第一个参数传递的函数。
所以[...aClass]
调用aClass[Symbol.iterator]
的调用上下文为aClass
.
循环从Runtime Semantics: ForIn/OfHeadEvaluationfor..of
获取迭代器,在这种情况下:
a. Assert: iterationKind is iterate.
b. Return GetIterator(exprValue).
导致与(使用 的调用上下文调用[...aClass]
迭代器)相同的事情aClass
aClass
推荐阅读
- lottie - 如何在 Lottie 动画开始播放之前消除延迟
- python - 在aiogram python中更新键盘
- excel - 消息框需要帮助
- typescript - 属性“baz”没有初始化程序,但通过构造函数中的方法调用完成
- r - 根据组/条件计算不同的标准误差
- java - 如何知道 log4j 何时创建了新的日志文件?
- spring - Spring - 如果模拟工作正常,如何@Autowired jpa 存储库
- python - 运行一个后台子进程,当它的父进程运行时它不会死掉(W10)
- amazon-web-services - Jenkins EC2 插件:实例未启动
- node.js - Nodemailer 错误:“路径”参数必须是字符串类型。收到未定义