JavaScript闭包两种函数写法输出结果不一致的原因咨询
JavaScript闭包实验输出差异解析
问题场景
学习JavaScript闭包(Closures)概念时编写了两组逻辑看似相近的测试代码,两组代码均设计为两次打印外层函数、内层函数内的变量值,但实际运行输出存在明显差异。
第一组:函数声明+内部直接调用实现
function outer1() { var j = 20; function inner1() { var k = 30; console.log(j, k); j++; k++; } inner1(); // 内部直接调用inner1 return; } outer1(); // 外部两次调用outer1 outer1();
运行输出:
20 30
20 30
两次输出结果完全相同。
第二组:返回内部函数的实现
function outer() { var a = 20; var inner = function() { var b = 30; console.log(a, b); a++; b++; } return inner; // 将内部函数作为返回值传出 } var func = outer(); // 仅调用一次outer,拿到返回的内部函数 func(); // 两次调用拿到的内部函数 func();
运行输出:
20 30
21 30
第二次调用时外层变量a的值递增了1。
差异核心原因
两组结果不同和「函数声明/函数表达式」的写法没有任何关系,本质区别是函数执行上下文的生命周期、以及闭包是否真正形成并持续持有外层变量:
- 第一组代码的执行逻辑:
每一次调用outer1(),都会创建一套全新的独立执行上下文:首先初始化局部变量j=20,接着定义内部函数inner1,随后在outer1内部直接执行一次inner1,完成打印、变量自增操作后,outer1执行完毕,它的整个执行上下文会被垃圾回收机制销毁,内部的变量j、k都会被清空回收。
第二次调用outer1()时,会重新创建一套全新的执行上下文,重新初始化j=20,重复执行一次内部逻辑,所以两次输出完全一致。这个场景下没有形成有效闭包——内部函数inner1只在outer1执行过程中存活,outer1运行结束后没有任何外部引用指向inner1,自然不会持续持有外层变量。 - 第二组代码的执行逻辑:
代码里仅调用了一次outer(),这次调用创建的执行上下文初始化了变量a=20、定义了内部函数inner,随后把inner的引用返回,赋值给了全局变量func。此时闭包正式形成:inner函数引用了外层作用域的a,且inner被全局变量持有,在outer执行结束后依然存活,因此outer的执行上下文不会被销毁,变量a会一直保存在内存中。
后续两次调用func(),本质是反复调用同一个存活的inner函数:- 第一次调用:新建函数内部局部变量
b=30,打印当前持有的外层变量a=20、局部变量b=30,随后a自增为21,b自增为31,函数执行结束后局部变量b被销毁; - 第二次调用:重新新建局部变量
b=30,但闭包持有的外层变量a已经是上次自增后的21,因此打印21 30,执行结束后b再次销毁,a继续保留在内存中。
- 第一次调用:新建函数内部局部变量
验证方式:如果把第一组代码改成
return inner1,仅调用一次outer1()拿到内部函数后反复调用,输出结果会和第二组完全一致;如果把第二组代码改成在outer内部直接调用两次inner、不返回内部函数引用,输出结果也会和第一组完全一致。
内容的提问来源于stack exchange,提问作者Nagesh Singh
相关产品推荐
相关产品推荐

