闭包技术疑问:两种JavaScript计数器实现为何输出不同?
闭包核心区别解析:为什么两个计数器结果不同?
嘿,这个问题问得太到位了,刚好能帮你把闭包的核心逻辑彻底搞清楚!先给你拆解两段代码的本质差异,再结合闭包的定义帮你理解。
先看两段代码的执行逻辑
第一段代码(正常累加)
var counter = (function(){ var count=0; return function(){ return count++; } }()); console.log(counter()); // 0 console.log(counter()); // 1 console.log(counter()); // 2
第二段代码(每次输出0)
var counter = function(){ var count=0; return function(){ return count++; } }; console.log(counter()()); // 0 console.log(counter()()); // 0 console.log(counter()()); // 0
核心区别:闭包的作用域创建时机与次数
首先得明确闭包的本质:闭包是内部函数能够记住并访问它的外层函数作用域,即使内部函数在外部执行。而这里的关键是:外层函数每调用一次,就会创建一个全新的作用域,对应的闭包也会绑定这个新作用域。
第一段代码:只创建一次闭包,共享同一个作用域
这里用了立即执行函数表达式(IIFE)——外层函数定义后立刻执行了一次:
- 执行外层函数时,创建了一个包含
count=0的作用域; - 返回的内部函数被赋值给了变量
counter,这个内部函数形成闭包,牢牢“抓住”了外层的count变量; - 之后每次调用
counter(),都是在同一个闭包的作用域里操作count,所以每次调用都会让count累加,结果自然是0、1、2。
第二段代码:每次调用都创建新闭包,作用域完全独立
这里的counter是一个普通函数,每次调用counter()都会触发以下流程:
- 创建一个全新的作用域,里面的
count被重新初始化为0; - 返回一个新的内部函数(这个函数绑定了当前新创建的作用域);
- 紧接着调用这个新内部函数(
counter()()),读取并返回当前作用域里的count(此时是0); - 调用结束后,这个新作用域没有被任何变量引用,很快被垃圾回收;
- 下次调用
counter()()时,又会重复上述步骤——新作用域、新count、新闭包,所以每次输出都是0。
一句话总结
闭包的作用域是和外层函数的调用绑定的,不是和函数定义绑定的。第一段代码只调用了一次外层函数,所以只有一个闭包共享同一个count;第二段代码每次调用都生成新的外层作用域和闭包,每个闭包的count都是独立的初始值0。
内容的提问来源于stack exchange,提问作者Mariia Sukhareva
相关产品推荐
相关产品推荐

