我试着在谷歌上搜索这个并查找类似的问题,但我似乎遗漏了一些基本的
let collection = {
items: [],
*[Symbol.iterator]() {
for (let item of this.items) {
yield item;
}
}
}
collection.items.push(1);
collection.items.push(2);
console.log(collection.next());
这会引发错误
console.log(collection.next());
^
TypeError: collection.next is not a function
根据我的阅读,我应该能够对集合对象使用next((,因为这会调用Symbol.iterator属性?
您需要调用[Symbol.iterator]()
方法来获得迭代器对象,然后对返回的对象调用next()
方法:
let collection = {
items: [],
*[Symbol.iterator]() {
for (let item of this.items) {
yield item;
}
}
};
collection.items.push(1);
collection.items.push(2);
let iterator = collection[Symbol.iterator]();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
请记住,数组本身已经实现了可迭代协议,事实上,您通过使用for...of
循环在[Symbol.iterator]()
定义中使用了该协议,因此collection
对象在这里并不是真正必要的:
let items = [];
items.push(1);
items.push(2);
let iterator = items[Symbol.iterator]();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
实际上有两种不同的协议
- "可读"-这是我使用
*[Symbol.iterator]()
生成器实现的。这允许。。。循环等
和
- "Terator"-意思是在对象上定义下一个方法
引用文档:
创建一个同时满足迭代器和可迭代协议的对象很容易(如下面的示例所示(。这样做允许迭代器被期望可迭代的各种语法所使用。因此,在不实现Iterable的情况下实现Iterator协议很少有用。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols
所以我重写了我的代码:
let collection = {
items: [],
*[Symbol.iterator]() {
for (let item of this.items) {
yield item;
}
},
i: 0,
next: function() {
let done = (this.i >= this.items.length);
let value = !done ? this.items[this.i++] : undefined
return {
done,
value
}
}
}
collection.items.push(1);
collection.items.push(2);
for (let i of collection) console.log(i); // demonstrates the iterable protocol
console.log(collection.next()); // demonstrates the iterator protocol
console.log(collection.next());
console.log(collection.next());
最后要注意的是,这不是一个私有对象,应该封装在一个类或立即调用的函数中,以避免这些属性可供任何其他代码访问。