无法在使用 *[Symbol.iterator]() 生成器 javascript 创建的可迭代对象上使用 next()
Posted
技术标签:
【中文标题】无法在使用 *[Symbol.iterator]() 生成器 javascript 创建的可迭代对象上使用 next()【英文标题】:Cannot use next() on iterable object created using *[Symbol.iterator]() generator javascript 【发布时间】:2020-10-18 21:17:54 【问题描述】:我试过用谷歌搜索这个并查看类似的问题,但我似乎遗漏了一些基本的东西
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 属性?
【问题讨论】:
不,.next()
在第一次调用返回的对象上。尝试在 for ... of
或 Array.from()
或类似的地方使用您的对象。
for (let i of collection) console.log(i);
返回我推入 items 数组属性的两个数字。所以这很好用,只是下一个方法不起作用。
【参考方案1】:
需要调用[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());
【讨论】:
我知道“数组”已经是任何可迭代的。我试图创建一个新的集合对象,它具有可以自定义的奇异属性。这可能是相当神秘的。但是我想我的想法是,一个新的可迭代对象可能不应该以单例样式创建next
方法,而是应该每次都创建一个迭代器,这样我们就可以同时运行多个迭代器。
@lindsaymacvean 是的。如果您的迭代器对象引用自己以便方便地用作可迭代对象,那么同一个对象应该实现两者的唯一时间,例如let iterator = [Symbol.iterator]() return this; , next() /* some non-trivial implementation */ ;
【参考方案2】:
实际上有两种不同的协议
'Iterable' - 这是我使用*[Symbol.iterator]()
生成器实现的。这允许 for...of 循环等。
和
'Iterator' - 表示在对象上定义下一个方法。引用文档:
创建一个同时满足迭代器和可迭代协议的对象很容易(如下例所示)。 这样做允许迭代器被期望迭代的各种语法消耗。因此,如果不实现 Iterable,实现 Iterator Protocol 很少有用。
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());
最后一点,这不是私有对象,应该包装在类中或立即调用的函数中,以避免任何其他代码等访问这些属性。
【讨论】:
以上是关于无法在使用 *[Symbol.iterator]() 生成器 javascript 创建的可迭代对象上使用 next()的主要内容,如果未能解决你的问题,请参考以下文章
我想在useEffect react Js中使用带有foreach的axios,但它给了我(无法读取属性Symbol(Symbol.iterator)错误?
更新状态 |对象不可迭代(无法读取属性 Symbol(Symbol.iterator))
无法读取未定义(递归函数)的属性“符号(Symbol.iterator)”