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

let在循环内外声明是否存在差异?关于let作用域的疑问

两段代码的核心差异解析

这两段代码有非常明显的差异,核心就在于let的块级作用域特性,以及for循环中let声明的特殊行为——我给你拆解开讲清楚:

1. 变量i的作用域范围完全不同

  • 示例1:let i是在循环外声明的,它的作用域覆盖整个外层区域(比如包裹这段代码的函数、或是全局作用域)。循环结束后,i仍然存在,你可以在循环外访问到它最后一次更新的值:

    // Example 1
    let i; 
    var arr = [1,2,3];
    for (i=0; i<arr.length; i++){
      // do stuff
    }
    console.log(i); // 输出:3,循环结束后i依然可访问
    
  • 示例2:let i是在for循环的初始化部分声明的,它的作用域被严格限制在循环体内部(包括循环的条件判断、更新表达式以及{}包裹的代码块)。循环结束后,i就会被销毁,外部无法访问:

    // Example 2
    var arr = [1,2,3];
    for (let i=0; i<arr.length; i++){
      // do stuff
    }
    console.log(i); // 报错:ReferenceError: i is not defined
    

2. 循环迭代中的变量实例不同

这是for循环里let声明容易被忽略的关键点:

  • 示例1的i是同一个变量,循环过程中只是不断更新它的值。如果循环里有异步操作(比如setTimeout),所有异步回调都会引用最后一次更新的i:

    let i;
    var arr = [1,2,3];
    for (i=0; i<arr.length; i++){
      setTimeout(() => {
        console.log(i); // 输出3次:3
      }, 100);
    }
    
  • 示例2的let i会在每一次循环迭代时创建一个新的变量实例,每个迭代的i都是独立的。异步回调会绑定当前迭代的那个i值:

    var arr = [1,2,3];
    for (let i=0; i<arr.length; i++){
      setTimeout(() => {
        console.log(i); // 依次输出:0、1、2
      }, 100);
    }
    

总结

简单说:

  • 示例1的i是「全局/外层作用域的变量,循环只是修改它的值」
  • 示例2的i是「循环专属的块级变量,每个迭代都有独立副本」

内容的提问来源于stack exchange,提问作者Henry Yang

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:59:47