Symbol.iterator 是 JavaScript 中使对象可被 for...of 遍历的内置接口,需在该属性上定义返回迭代器对象的函数,迭代器必须有返回 {value, done} 的 next() 方法。

Symbol.iterator 是 JavaScript 中让一个对象“可被 for...of 遍历”的关键机制,它不是“需要”被手动写出来,而是语言内置的约定接口——只要对象有这个属性且返回一个符合规范的迭代器,就能参与 for...of、扩展运算符([...obj])、解构、Array.from() 等操作。
它定义了“怎么一步步取值”的规则
一个对象要支持迭代,必须在 [Symbol.iterator] 属性上提供一个函数,这个函数被调用后必须返回一个迭代器对象。这个迭代器对象必须有 next() 方法,每次调用都返回形如 { value: ..., done: true|false } 的对象。
比如,手动实现一个可遍历的计数器:
const counter = {
from: 1,
to: 3,
[Symbol.iterator]() {
let current = this.from;
return {
next() {
if (current <= this.to) {
return { value: current++, done: false };
} else {
return { value: undefined, done: true };
}
}
};
}
};
for (const num of counter) {
console.log(num); // 1, 2, 3
}
原生类型靠它统一迭代逻辑
数组、字符串、Map、Set、TypedArray 等内置类型都默认实现了 [Symbol.iterator],所以它们天然支持 for...of。比如:
立即学习“Java免费学习笔记(深入)”;
-
[1,2,3][Symbol.iterator]()返回数组迭代器,按索引顺序产出元素 -
"abc"[Symbol.iterator]()返回字符串迭代器,按 Unicode 码点产出字符(不是字节) -
new Map([[1,'a'],[2,'b']])[Symbol.iterator]()返回键值对迭代器(等价于.entries())
它是协议,不是语法糖
for...of 并不关心对象是不是数组或类数组;它只检查有没有 [Symbol.iterator] 方法。没有它,哪怕有 length 和数字索引(比如普通对象 {0:'a',1:'b',length:2}),也无法被 for...of 遍历——因为没告诉引擎“从哪开始、怎么往下走、什么时候停”。
你可以随时给任意对象添加这个方法来赋予迭代能力,比如让一个 DOM 节点列表像数组一样被展开:
NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
// 现在 [...document.querySelectorAll('div')] 就能用了
注意:它不改变对象本身结构
定义 Symbol.iterator 不会自动添加 forEach、map 这些方法,也不会让对象变成数组。它只启用“按需逐个取值”这一种行为,是轻量、明确、可组合的协议。
基本上就这些——它不是语法必需,却是让数据“活起来”、被现代遍历语法识别的桥梁。











