目录
一、什么是闭包?
二、闭包的四大核心应用
1. 封装私有变量(模块模式)
2. 防抖/节流函数(性能优化)
3. 柯里化函数(函数式编程)
4. 循环中保留变量(解决经典面试题)
三、闭包的三大注意事项
四、高频面试题解析
五、总结
一、什么是闭包?
定义:当一个函数能够记住并访问其所在的词法作用域(即使函数在其作用域外执行),就产生了闭包。
简单说:闭包 = 函数 + 函数创建时的作用域链
function outer() {let count = 0; // 闭包捕获的变量return function inner() {count++;return count;};
}const counter = outer();
console.log(counter()); // 1
console.log(counter()); // 2 (count状态被保留)
二、闭包的四大核心应用
1. 封装私有变量(模块模式)
const createUser = () => {let privateName = "Unknown";return {getName: () => privateName,setName: (name) => { privateName = name }};
};const user = createUser();
console.log(user.getName()); // "Unknown"
user.setName("John");
console.log(user.getName()); // "John"
2. 防抖/节流函数(性能优化)
// 防抖实现
function debounce(fn, delay) {let timer = null;return function(...args) {clearTimeout(timer);timer = setTimeout(() => fn.apply(this, args), delay);};
}window.addEventListener("resize", debounce(() => {console.log("窗口停止变化后执行");
}, 300));
3. 柯里化函数(函数式编程)
const add = (a) => (b) => a + b;
const add5 = add(5);
console.log(add5(3)); // 8
4. 循环中保留变量(解决经典面试题)
// 错误写法(输出全为5)
for (var i = 0; i < 5; i++) {setTimeout(() => console.log(i), 100);
}// 闭包修正
for (var i = 0; i < 5; i++) {((j) => {setTimeout(() => console.log(j), 100);})(i);
}
三、闭包的三大注意事项
1. 内存泄漏风险
function leakMemory() {const hugeArray = new Array(1000000).fill("data");return () => console.log("闭包持有hugeArray!");
}
// 使用后需主动解除引用:leakMemory = null;
2.避免过度使用:大量闭包会增加内存消耗和解析时间
3.this指向问题
const obj = {name: "Alice",say: function() {return () => console.log(this.name); // 箭头函数解决this问题}
};
四、高频面试题解析
Q1:以下代码输出什么?
for (let i = 0; i < 3; i++) {setTimeout(function() {console.log(i);}, 100);
}
// 输出:0, 1, 2 (let创建块级作用域)
Q2:实现一个计数器工厂函数
const createCounter = (init = 0) => {let count = init;return {inc: () => ++count,dec: () => --count,get: () => count};
};
五、总结
特性 | 说明 |
---|---|
数据封装 | 创建私有变量,实现模块化 |
状态保持 | 函数记忆上下文状态 |
内存消耗 | 不当使用会导致内存泄漏 |
应用场景 | 防抖节流、柯里化、模块开发 |
最佳实践:在需要封装状态/行为时使用闭包,但注意及时释放不再需要的闭包引用。
推荐阅读:
-
《You Don't Know JS》闭包章节
-
MDN Closures文档
源码地址:GitHub闭包示例库
点赞支持:如果本文对你有帮助,欢迎点赞+收藏!