为什么自定义迭代器在 for…of 里不生效?
我写了个对象想用 for…of 遍历,但根本进不去循环,是不是哪里搞错了?
我给对象加了 Symbol.iterator 方法,也 return 了一个带 next 的对象,但就是没效果:
const myObj = {
data: [1, 2, 3],
[Symbol.iterator]() {
let index = 0;
return {
next: () => {
if (index < this.data.length) {
return { value: this.data[index++], done: false };
}
return { done: true };
}
};
}
};
for (const item of myObj) {
console.log(item); // 根本没输出!
}
奇怪的是,如果我把 iterator 方法写成普通函数再手动调用 .next() 是能拿到值的,但 for…of 就不行,这是为啥?
this上。你用的是箭头函数,箭头函数的this是词法绑定的,它不会指向myObj,而是指向定义时所在的上下文(通常是window或undefined),所以this.data是undefined,自然就进不了循环。你手动调用
.next()能工作,是因为你可能是在全局作用域下直接调的,但for...of内部调用时,箭头函数里的this还是没绑定对。改法很简单,把
next改成普通函数,或者用变量先把data抓出来:const myObj = {data: [1, 2, 3],
[Symbol.iterator]() {
const data = this.data;
let index = 0;
return {
next() {
if (index < data.length) {
return { value: data[index++], done: false };
}
return { done: true };
}
};
}
};
或者更简洁点,直接用生成器函数,可读性更高:
const myObj = {data: [1, 2, 3],
*[Symbol.iterator]() {
for (const item of this.data) {
yield item;
}
}
};
这两种都能让
for...of正常跑起来。生成器那版是更好的写法,少写不少样板代码,也避免了this和箭头函数的坑。