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

闭包技术疑问:两种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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:22:52