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

为何两段仅变量名不同的JavaScript代码输出结果不同?

为什么两段看似相似的代码输出不同?

嘿,这个问题其实藏着一个很经典的var作用域陷阱,我来给你拆解清楚——根本不是funcs和fun的变量名差异导致的,而是第二个循环用的变量不一样!

先直接说两段代码的实际输出:

  • Sample 1会连续输出三次 My value: 3
  • Sample 2会依次输出 values is 0、values is 1、values is 2

核心原因:var的函数级作用域特性

var声明的变量是函数级作用域,没有块级作用域——也就是说,不管你在多少个for循环里写var i,只要在同一个函数(这里是全局函数)里,它们都是同一个变量。

先看Sample 1的执行流程

  1. 全局作用域里会提前声明所有var变量:funcs、i、j(这就是变量提升)
  2. 第一个for循环:i从0走到2,每次给funcs[i]赋值一个匿名函数。注意:这个函数里的console.log引用的是全局的i变量,不是循环里的局部变量
  3. 第一个循环结束后,i的值会变成3(因为i++后不满足i<3,退出循环)
  4. 第二个for循环用的是独立的j,从0走到2,每次调用funcs[j]()。这时候函数里引用的i还是全局的那个i,值是3,所以三次输出都是My value: 3

再看Sample 2的执行流程

  1. 全局作用域里提前声明fun和i(两个for循环里的var i都是同一个全局变量,重复声明不会创建新变量)
  2. 第一个for循环结束后,i的值同样是3
  3. 第二个for循环开始:直接给全局的i重新赋值为0(var i在这里只是重复声明,不起作用)
  4. 每次调用fun[i]()的时候,函数里引用的i是当前全局的i——也就是第二个循环的当前索引值:
    • 第一次调用时i=0,输出values is 0
    • 第二次调用时i=1,输出values is 1
    • 第三次调用时i=2,输出values is 2

如何让两段代码输出一致?

如果想让Sample 1也输出0、1、2,有两种常用方法:

  1. 用ES6的let声明循环变量(let有块级作用域,每个循环迭代都会创建独立的变量):
var funcs = [];
for (let i = 0; i < 3; i++) {
    funcs[i] = function() { console.log("My value: " + i); };
}
for (var j = 0; j < 3; j++) {
    funcs[j]();
}
  1. 用立即执行函数(IIFE)创建局部作用域:
var funcs = [];
for (var i = 0; i < 3; i++) {
    (function(currentI) {
        funcs[currentI] = function() { console.log("My value: " + currentI); };
    })(i);
}
for (var j = 0; j < 3; j++) {
    funcs[j]();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:25:32