js闭包
闭包指的是一个函数可以记住它被创建时的变量作用域,当函数在这个作用域之外执行时,依然能够访问该作用域内的变量。
function createCounter() {
let count = 0; // 闭包中的私有变量
return function() {
count += 1;
return count;
};
}
const counter1 = createCounter();
console.log(counter1()); // 输出 1
console.log(counter1()); // 输出 2
const counter2 = createCounter();
console.log(counter2()); // 输出 1(counter2 是独立的)
在上面例子中,createCounter 函数返回了一个内部函数,这个内部函数形成了一个闭包,它可以访问并更新外层的 count 变量。这样,count 就被封装在 createCounter 的作用域中,外部无法直接访问或修改它,只能通过 counter1() 这样的调用来操作 count。
关键点总结
- 闭包可以访问函数定义时的词法作用域,即使该函数在外部被调用。
- 通过闭包可以保护变量,防止全局污染,便于数据封装。
- 闭包也有可能引发内存泄漏,因为被引用的变量在作用域外仍然存在,不会被垃圾回收器释放。
如何避免闭包引起的内存泄漏
1.闭包会保持对外部函数变量的引用。如果外部函数中的变量在闭包执行完后不再使用,可以手动断开这些引用,让垃圾回收器能够回收不再使用的内存。
function outer() { let largeObject = { name: 'Big Object', data: new Array(1000).fill(0) }; return function inner() { console.log('I am a closure'); }; } const closure = outer(); // 使用完毕后,关闭引用 closure = null; // 删除闭包引用
2.避免在长时间存活的闭包中保存大量数据:如果闭包在全局范围内或长时间存活的地方持有了大量的数据,可能会导致内存泄漏。例如,事件监听器中的闭包,如果不及时移除,可能会导致 DOM 元素无法被回收。
function createEventHandler() { const largeData = new Array(1000).fill(0); // 很大的数据 return function(event) { console.log('Event triggered'); }; } const handler = createEventHandler(); document.getElementById('some-element').addEventListener('click', handler); // 如果不移除事件监听器,闭包将一直存在,导致内存泄漏

浙公网安备 33010602011771号