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

JavaScript闭包入门问题:为何计数器函数未按预期工作?

问题分析与解决

你的代码没达到预期效果,核心是对闭包的执行时机和状态保存逻辑理解有偏差,我来帮你拆解清楚:

1. 核心问题出在哪

(1)逻辑执行时机错了

当你执行let shopping = counter();时,没有传入key参数,函数内部的两个if判断根本不会触发,counter保持初始值10。而且这两个判断是在创建返回函数的那一刻执行一次,不是每次调用shopping时都执行。

(2)返回的函数没处理参数

你返回的匿名函数根本没有接收key参数,所以后面调用shopping('milk')时,传的参数完全没被用到,自然不会修改counter的值。

(3)闭包的状态没被正确利用

你想让shopping持续保存counter的状态,但现在返回的函数只是固定打印第一次创建时的counter值(也就是10),没有把修改逻辑放到返回的函数内部。


修正后的代码

把修改counter的逻辑放到返回的函数里,让它接收key参数,这样每次调用shopping时都会更新闭包保存的状态:

let counter = () => { 
  // 这个counter变量会被闭包永久保存,不会重复初始化
  let counter = 10; 
  // 返回的函数接收key参数,每次调用时处理计数逻辑
  return function(key) { 
    if (key === 'milk') { ++counter; } 
    if (key === 'bread') { --counter; } 
    console.log(counter);
  } 
} 

let shopping = counter(); 
shopping('milk'); // 输出11
shopping('milk'); // 输出12
shopping('bread'); // 输出11
shopping('bread'); // 输出10

为什么这样就生效了?

  • 当你调用counter()时,会创建一个局部变量counter(初始值10),然后返回一个内部函数。这个内部函数会捕获并保留对counter变量的引用——这就是闭包的核心作用,让函数能访问并修改外部作用域的变量。
  • 每次调用shopping(key)时,都会执行内部函数里的逻辑,根据传入的key更新闭包保存的counter值,然后打印最新状态。
  • 因为counter是在counter()的局部作用域里,不会被外部代码污染,也不会在每次调用shopping时重新初始化,所以状态能持续保留下来。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 00:32:55