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():- 初始化作用域,提升
chiffre和multiplicateur的声明。 chiffre被赋值为10。- 定义闭包函数
fonction,此时它只是记住要去外部作用域找chiffre和multiplicateur,但不会立刻读取它们的值。 chiffre = chiffre * 2,此时chiffre变成20。multiplicateur = 10,给之前提升的变量赋值为10。- 返回闭包函数,
maFonction指向这个函数。
- 初始化作用域,提升
- 调用
maFonction():
闭包此时去外部作用域读取chiffre和multiplicateur的当前值——chiffre=20,multiplicateur=10,计算20*10=200,所以输出200。
总结一下
- 你觉得
multiplicateur是闭包定义后才声明的,其实是var的变量提升让它的声明提前了,闭包知道这个变量存在。 - 闭包调用时才会去取变量的当前值,这时候
chiffre已经被更新为20,multiplicateur也完成了赋值,所以能得到200的结果。
内容的提问来源于stack exchange,提问作者Alicia
相关产品推荐
相关产品推荐

