MST

星途 面试题库

面试题:JavaScript 公认符号之闭包的复杂应用场景

描述 JavaScript 闭包在实现模块模式和封装私有变量方面的应用场景。请编写一个 JavaScript 模块,使用闭包来封装一个计数器变量,使其只能通过特定的公共方法进行访问和修改,同时解释闭包在这个场景下的工作原理以及可能带来的内存问题。
24.1万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

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. 闭包工作原理

  • 在上述代码中,外层函数自调用并返回一个对象,该对象包含了三个公共方法:incrementdecrementgetCount
  • 闭包在这里起到关键作用,counter 变量定义在外层函数内部,正常情况下,外层函数执行完毕后,其内部变量会被垃圾回收。但由于返回的对象中的方法(incrementdecrementgetCount)引用了 counter 变量,JavaScript 的闭包机制使得 counter 变量不会被回收,依然存在于内存中。这样就实现了 counter 变量的封装,只能通过返回对象中的公共方法来访问和修改它。

3. 可能带来的内存问题

  • 内存泄漏风险:因为闭包会使被引用的变量一直保存在内存中,如果在模块的使用过程中,这些公共方法被频繁调用且长时间持有引用,那么 counter 变量以及相关的作用域链就会一直占用内存,无法被垃圾回收机制回收,从而可能导致内存泄漏。特别是在一些需要长时间运行的应用(如单页应用)中,如果不合理使用闭包来封装变量,可能会随着时间推移导致内存占用不断增加,影响应用性能。
  • 内存开销增大:由于闭包会保存整个作用域链,不仅是被引用的变量,还包括作用域链上的其他变量和对象。如果闭包引用的作用域链中包含大量数据或者复杂对象,会增加额外的内存开销,降低应用的运行效率。