JavaScript迭代器对象内定义[Symbol.iterator]()方法的作用是什么
核心解答
你遇到的问题本质和JavaScript的两套迭代协议有关:可迭代协议、迭代器协议。
1. 迭代器对象内的[Symbol.iterator]() { return this; }作用是什么?为什么删除后你的示例还能运行?
这段代码的作用是让迭代器对象本身也符合可迭代协议,让迭代器可以被直接当成可迭代对象使用。
你删除后示例依然能跑,是因为你的测试场景只用到了SayHi实例的可迭代能力:for...of遍历sayHi实例时,会先调用实例的Symbol.iterator方法拿到迭代器,之后只调用迭代器的next()方法完成遍历,不会再检查迭代器本身是否可迭代,所以有没有这段代码不影响你的测试用例运行。
只有当你需要直接遍历迭代器本身的时候,这段代码才会生效,比如下面的用法如果没有这段代码就会报错:
let sayHi = new SayHi("HI", 3); // 手动拿到迭代器对象 const iterator = sayHi[Symbol.iterator](); // 直接遍历迭代器对象 for(let x of iterator) { console.log(x); }
如果迭代器没有实现Symbol.iterator方法,上面的代码会抛出iterator is not iterable的错误。加上这段代码后,迭代器本身就满足可迭代协议的要求,调用iterator[Symbol.iterator]()返回自身,就可以正常遍历。
这种设计是JavaScript的通用最佳实践,所有内置的迭代器(比如数组调用values()/keys()返回的迭代器、Map/Set的迭代器)都实现了这个逻辑,保证迭代器本身也可以被for...of、扩展运算符、Array.from等接收可迭代对象的API直接使用。
2. 外层[Symbol.iterator]返回的两个方法分别在什么场景调用?
外层Symbol.iterator返回的对象同时满足迭代器协议和可迭代协议,两个方法的调用场景如下:
next():迭代器协议要求的核心方法,所有迭代操作(for...of遍历、扩展运算符、Array.from、解构赋值等)都会循环调用这个方法,直到返回的对象中done属性为true时停止迭代。- 迭代器上的
[Symbol.iterator]():只有当你把这个迭代器对象本身作为可迭代对象传入需要可迭代对象的API时才会被调用,作用是返回迭代器自身,让迭代器可以被直接迭代。
内容的提问来源于stack exchange,提问作者maxloo
相关产品推荐
相关产品推荐

