1. 代码实现
const counterModule = (function () {
let counter = 0;
return {
increment: function () {
counter++;
return counter;
},
decrement: function () {
if (counter > 0) {
counter--;
}
return counter;
},
getCount: function () {
return counter;
}
};
})();
2. 闭包工作原理
- 在上述代码中,外层函数自调用并返回一个对象,该对象包含了三个公共方法:
increment
、decrement
和 getCount
。
- 闭包在这里起到关键作用,
counter
变量定义在外层函数内部,正常情况下,外层函数执行完毕后,其内部变量会被垃圾回收。但由于返回的对象中的方法(increment
、decrement
、getCount
)引用了 counter
变量,JavaScript 的闭包机制使得 counter
变量不会被回收,依然存在于内存中。这样就实现了 counter
变量的封装,只能通过返回对象中的公共方法来访问和修改它。
3. 可能带来的内存问题
- 内存泄漏风险:因为闭包会使被引用的变量一直保存在内存中,如果在模块的使用过程中,这些公共方法被频繁调用且长时间持有引用,那么
counter
变量以及相关的作用域链就会一直占用内存,无法被垃圾回收机制回收,从而可能导致内存泄漏。特别是在一些需要长时间运行的应用(如单页应用)中,如果不合理使用闭包来封装变量,可能会随着时间推移导致内存占用不断增加,影响应用性能。
- 内存开销增大:由于闭包会保存整个作用域链,不仅是被引用的变量,还包括作用域链上的其他变量和对象。如果闭包引用的作用域链中包含大量数据或者复杂对象,会增加额外的内存开销,降低应用的运行效率。