makeacounter 本质是编程里非常经典的自定义计数器函数,核心作用就是创建一个可以持续自增的计数器,每次调用这个计数器,数值就会在上一次的基础上加一,最典型的实现方式是利用闭包,让内部变量可以被保留,不会在函数执行完就销毁,很多初学者在 JavaScript 学习阶段会专门练习 makeacounter 这个题目,属于闭包知识点的标准例题,除了 JS 之外其他编程语言也可以按照同样思路实现 makeacounter,只是语法写法不一样,这个练习重点不是单纯做加法,而是理解状态持久保存,也就是多次调用之间,计数器的数值不会重置。
为什么需要 makeacounter
普通函数里面定义的局部变量,函数运行结束之后内存就会释放,下一次调用函数的时候变量又会从初始值重新开始,没办法记住上一次的数字。makeacounter 就是解决这个痛点,通过闭包把内部变量包裹起来,外部只能通过返回的函数修改和读取这个计数,实现私有状态,外部代码不能直接篡改内部计数,这也是 makeacounter 最核心的设计价值。
| 对比项 | 普通自增函数 | makeacounter 闭包版本 |
|---|---|---|
| 变量生命周期 | 单次调用结束就销毁 | 多次调用持续保留 |
| 初始值 | 每次调用都重置 | 只初始化一次 |
| 变量访问 | 外部可以直接修改 | 内部私有,外部不能直接改 |
| 适用场景 | 一次性计算 | 需要累计计数场景 |
JavaScript 版本 makeacounter 实现步骤
第一步 编写外层函数,函数名称就是 makeacounter,在外层函数内部声明 count 变量,初始值一般设置为 0。
第二步 在外层函数里面定义内部函数,内部函数执行 count 加一,然后返回最新的 count 数值。
第三步 外层函数把内部函数 return 返回出去。
第四步 调用 makeacounter,把返回结果保存到一个变量,之后每次调用这个变量,就会执行自增,计数持续累加。
基础代码示例
function makeacounter (){
let count = 0
return function (){
count++
return count
}
}
const counter = makeacounter ()
counter () // 1
counter () // 2
counter () // 3
扩展变种
可以修改 makeacounter,支持自定义初始值,调用的时候传入起始数字,还可以增加重置功能,新增 reset 方法,让计数器可以清零,也可以做成支持递减版本,这些都是 makeacounter 基础题的拓展考题,面试当中经常会在原题基础上增加这类改造要求。
综合来看 makeacounter 是闭包入门经典练习题,核心原理就是利用闭包保留局部变量状态,实现多次调用持续累加计数器,面试和前端基础测试高频出现,掌握这个例子之后,就能理解闭包保存私有状态这个核心思想。
【常见问题】
问题 1 makeacounter 为什么每次调用计数不会归零
回答 1 makeacounter 依靠闭包特性,内部 count 变量属于外层函数作用域,内部返回的函数一直引用这个变量,外层函数只执行初始化一次,所以 makeacounter 多次调用返回的函数时 count 不会重置归零。
问题 2 makeacounter 可以用全局变量代替实现吗
回答 2 makeacounter 可以借助全局变量写出自增效果,但是全局变量会污染作用域,还能被外部随意修改,丢失 makeacounter 原本私有状态的设计优势,所以标准 makeacounter 不推荐使用全局变量方案。
问题 3 makeacounter 如果新建第二个实例计数是独立的吗
回答 3 makeacounter 每一次调用 makeacounter 都会生成一份独立的 count 变量,新建第二个实例之后,两个计数器的数值互相隔离,各自累加,不会互相影响,这也是 makeacounter 闭包方案很重要的特性。
【免责申明】
本文为编程教学讲解内容,代码示例仅用于学习演示,不同编程环境运行结果可能存在语法差异,实际项目使用 makeacounter 需要结合业务场景做优化,本文不构成项目开发的强制标准方案。


