ES6中for-in、for-of与for(;;)循环变量作用域差异问询
ES6中for-in、for-of与传统for循环的变量生命周期问题
这个问题其实戳中了ES6里不同循环结构在变量绑定上的核心差异,咱们一步步拆解清楚:
核心结论先给你
- 用
const/let声明的for-in、for-of循环变量,每次迭代都会生成一个全新的绑定,而且这个变量的作用域只限于当前迭代的循环块,迭代结束后就会失效,外部根本访问不到。 - 传统
for(;;)循环里的变量(不管let还是const),是在循环头部的作用域里只声明一次,整个循环共享同一个绑定——这也是为什么用const会报错的原因。
1. for-in/for-of为啥能用const?变量又为啥会失效?
你贴的这两个例子能正常跑,完全符合规范:
for (const i in ["red", "green", "blue"]) { console.log(i) } // 输出 0 1 2 for (const i of ["red", "green", "blue"]) { console.log(i) } // 输出 red green blue
ES6里特意给for-in和for-of设计了「每次迭代创建新变量绑定」的逻辑,说白了就是每次循环时的i都是一个全新的常量,它被赋值为当前迭代的键(for-in)或者值(for-of),因为整个迭代过程中不需要修改这个i,所以用const完全没问题。
而且这个i的作用域被严格限制在当前迭代的{}块里,循环结束后你再去访问i,会直接抛出ReferenceError,证明它已经失效了:
for (const i of ["red", "green", "blue"]) { console.log(i) } console.log(i); // ReferenceError: i is not defined
2. 传统for循环为啥用const会报错?
再看第三个例子:
for (const i = 0; i < 10; i++) { console.log(i) } // 抛出 TypeError: Assignment to constant variable.
这是因为传统for循环的变量声明是在初始化阶段就完成了,整个循环过程中只有一个i的绑定。当执行i++时,本质是给这个已经声明好的常量i赋值,这就违反了const的只读规则,自然会报错。
哪怕换成let,整个循环里的i也是同一个变量,每次迭代只是修改它的值——不过ES6里let会把这个变量的作用域限制在循环结构内,外部还是访问不到。
3. 这不是隐晦规则,规范里写得明明白白
这个差异在ES6(ECMAScript 2015)规范里有明确定义:
- 对于for-in和for-of循环,每次迭代都会创建一个新的变量环境,循环变量在这个新环境中声明,所以每个迭代的变量都是独立的个体。
- 对于传统的
for(;;)循环,变量声明是在循环的初始化步骤中完成的,整个循环共享同一个变量环境,变量从头到尾都是同一个绑定。
说白了就是两种循环的设计目标不同:for-in/for-of是用来遍历集合元素的,每个元素对应独立的变量很合理;而传统for循环是计数循环,需要一个持续变化的计数器,共享绑定才符合需求。
内容的提问来源于stack exchange,提问作者nonopolarity
相关产品推荐
相关产品推荐

