面试题答案
一键面试可能导致内存泄漏的闭包场景举例
假设我们有一个简单的网页应用,其中包含一个按钮,每次点击按钮时,会创建一个新的闭包来处理一些逻辑。
function createButton() {
const button = document.createElement('button');
button.innerHTML = 'Click me';
document.body.appendChild(button);
button.onclick = function() {
const largeData = new Array(1000000).fill(1); // 模拟大量数据
console.log('Button clicked, largeData:', largeData);
};
}
createButton();
在这个例子中,每次点击按钮,都会创建一个新的闭包。由于闭包引用了外部函数作用域中的button
元素,并且闭包内部创建了一个巨大的数组largeData
。如果按钮被频繁点击,这些闭包及其内部的大量数据就不会被垃圾回收机制回收,从而导致内存泄漏。
解决该问题的方法
- 解除闭包对外部变量的引用:在闭包执行完毕后,手动解除对外部变量(如
button
)的引用。
function createButton() {
const button = document.createElement('button');
button.innerHTML = 'Click me';
document.body.appendChild(button);
button.onclick = function() {
const largeData = new Array(1000000).fill(1);
console.log('Button clicked, largeData:', largeData);
// 点击后解除闭包对button的引用
button.onclick = null;
};
}
createButton();
- 使用WeakMap:如果闭包需要在一定时间内保持对外部对象的引用,可以使用
WeakMap
。WeakMap
中的键是弱引用,当键对象不再有其他强引用时,WeakMap
不会阻止键对象被垃圾回收。
const weakMap = new WeakMap();
function createButton() {
const button = document.createElement('button');
button.innerHTML = 'Click me';
document.body.appendChild(button);
const largeData = new Array(1000000).fill(1);
weakMap.set(button, largeData);
button.onclick = function() {
const data = weakMap.get(button);
console.log('Button clicked, largeData:', data);
};
}
createButton();
在这种情况下,当button
元素从DOM中移除且不再有其他强引用时,WeakMap
中的对应项也会被垃圾回收机制回收,避免了内存泄漏。