在JavaScript ES6中,iterable [Symbol.iterator]被绑定为带有this且与iterable绑定,但是Mozilla和ES6规范均未提及它?

问题描述 投票:-1回答:2

当前,Mozilla specsES6 specs都提到对于可迭代的obj,以下含义:

[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实现规范提到了它……但是我认为界面应该告诉所有有关它的使用方式,并且不应该要求用户也阅读实现)。

javascript ecmascript-6 iterable
2个回答
0
投票

您可以通过编程将所需的.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

GetIterator

a. Let method be GetMethod(obj, @@iterator). ... 3. Let iterator be Call(method,obj). 是传递的第一个参数(对于obj,它是ArrayAccumulation)。

spreadObj的作用是调用第二个参数的调用上下文(Call)作为第一个参数传递的函数。

因此,this使用[...aClass]的调用上下文调用aClass[Symbol.iterator]

aClass循环从for..of获取迭代器,在这种情况下,这样做:

Runtime Semantics: ForIn/OfHeadEvaluation

[与a. Assert: iterationKind is iterate. b. Return GetIterator(exprValue). 产生相同的结果([...aClass]上的迭代器通过aClass的调用上下文被调用)


-1
投票

我们可以通过检查ES6中内置Collections的行为和实现来学到很多东西,这将表明aClass函数只是一个普通方法,其行为与所有其他普通方法一样。它对调用它的对象进行操作。它不是绑定函数。

© www.soinside.com 2019 - 2024. All rights reserved.