You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在含多个循环的函数中使用var的疑问及与let的区别对比

问题核心澄清

你产生困惑的核心原因是误解了《JavaScript: The Definitive Guide》中描述的适用前提:文中所说的「多个for循环中用var无危害」,特指平级非嵌套的for循环,并不包含你测试的嵌套循环场景。

1. 犀牛书描述的正确场景验证

当多个for循环是平级关系时,var的特性确实不会引发问题:

function test() {
  // 第一次声明并初始化函数作用域的变量i
  for(var i = 0; i < 2; i++) {
    console.log('第一个循环:', i)
  }
  // 这里重复写的var i会被JS引擎自动忽略(因为同一函数作用域下var允许重复声明)
  // 仅会执行i=0的赋值操作,重置外层i的值,第二个循环可以正常运行
  for(var i = 0; i < 2; i++) {
    console.log('第二个循环:', i)
  }
}

这段代码的输出是0 1 0 1,两个循环都能正常执行,不会报错,这就是原文所说的「无危害」的场景,也是ES6普及之前很多老JS代码的常见写法。

2. 嵌套场景下var的问题

你测试的嵌套循环用var不符合预期,正是因为var只有函数作用域,内外层循环共享同一个变量i:

(function foo() {
    for (var i = 0; i < 2; i++) { // 初始化函数作用域的i为0
        console.log(i); // 第一次外层循环输出0
        for (var i = 0; i < 2; i++) { // 直接修改同一个i的值为0,内层循环执行完后i变为2
            console.log(i); // 输出0、1
        }
        // 此时i=2,外层循环的判断条件i<2不成立,直接终止循环,因此外层仅执行1次
    }
})();

这段代码最终输出为0 0 1,和你预期的结果不符,这就是var没有块级作用域在嵌套场景下的典型坑点,原文并没有说这种场景下var无危害。

3. let的块级作用域特性

你测试的let不管是平级还是嵌套场景都能正常运行,是因为let支持块级作用域:

  • 平级的两个for循环:每个for循环头部声明的let i,作用域仅属于当前循环块,两个i是完全独立的变量,互不干扰,因此两个循环都能正常输出0 1
  • 嵌套的for循环:外层的let i作用域是外层循环块,内层的let i作用域是内层循环块,两者是独立变量不会互相覆盖,因此能输出你预期的0 0 1 1 0 1结果。

4. var和let的核心区别总结

  • 作用域不同:var只有全局作用域和函数作用域,let支持块级作用域(所有{}包裹的区域,包括for循环的块都是独立作用域)
  • 重复声明规则不同:同一作用域下var允许重复声明同名变量,后续声明会被自动忽略,仅保留赋值逻辑;let重复声明会直接抛出语法错误
  • 变量提升不同:var存在变量提升,可以在声明前访问,值为undefined;let存在暂时性死区,声明前访问会直接报错

目前行业最佳实践是默认使用let/const代替var,可以避免绝大多数作用域污染导致的隐性bug。


内容的提问来源于stack exchange,提问作者Koray Tugay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.14 12:15:02