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

JS闭包疑问:执行结果为200的原因?后声明变量为何可被识别?

为什么闭包调用后输出200,且能识别后续声明的multiplicateur?

这个问题问到了JavaScript里两个非常关键的知识点:变量提升(Hoisting)和闭包的作用域绑定时机,咱们一步步拆解来理解:

1. 先搞懂「变量提升」是怎么回事

JavaScript引擎在执行代码前,会先对整个作用域的声明做预处理:

  • 用var声明的变量,会把变量声明提升到当前作用域的最顶部,但赋值操作会留在原地。
  • 对于你的代码来说,multiplicateur虽然写在闭包函数之后,但在multiplicationParDeux函数的作用域里,它的声明其实已经被提升到了作用域开头,相当于:
    function multiplicationParDeux() {
      var chiffre; // 提升声明
      var multiplicateur; // 提升声明
      chiffre = 10;
      var fonction = function() {
        console.log(chiffre * multiplicateur);
      }
      chiffre = chiffre * 2;
      multiplicateur = 10; // 赋值留在原地
      return fonction;
    }
    
    所以闭包函数定义的时候,multiplicateur已经是当前作用域里存在的变量了,只是还没被赋值而已。

2. 闭包的「变量访问时机」是调用时,不是定义时

闭包的核心特性是:它会保留对外部作用域的引用,但它访问变量的取值是在闭包被调用的时候,不是定义的时候。

咱们跟着代码执行流程走一遍,就能明白为什么输出200:

  • 调用multiplicationParDeux():
    1. 初始化作用域,提升chiffre和multiplicateur的声明。
    2. chiffre被赋值为10。
    3. 定义闭包函数fonction,此时它只是记住要去外部作用域找chiffre和multiplicateur,但不会立刻读取它们的值。
    4. chiffre = chiffre * 2,此时chiffre变成20。
    5. multiplicateur = 10,给之前提升的变量赋值为10。
    6. 返回闭包函数,maFonction指向这个函数。
  • 调用maFonction():
    闭包此时去外部作用域读取chiffre和multiplicateur的当前值——chiffre=20,multiplicateur=10,计算20*10=200,所以输出200。

总结一下

  • 你觉得multiplicateur是闭包定义后才声明的,其实是var的变量提升让它的声明提前了,闭包知道这个变量存在。
  • 闭包调用时才会去取变量的当前值,这时候chiffre已经被更新为20,multiplicateur也完成了赋值,所以能得到200的结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:58:18