“闭包本质上是一个函数,它能访问并记住其词法作用域,即使该函数在其词法作用域之外执行。
它的核心价值在于数据私有化和状态保持。
在实际开发中,我常用它来实现模块化封装(防止全局污染)、防抖节流函数、以及函数柯里化。
不过在使用时需要注意,闭包会让变量常驻内存,使用不当容易造成内存泄漏,所以在不需要的时候需要手动将引用置空。”
代码示例:
正常情况下,函数执行完,其内部变量会被销毁(垃圾回收)。
但闭包的特殊之处在于:外部函数执行完毕后,其作用域链依然被内部函数引用着,导致外部函数的变量对象(AO)无法被回收,依然保存在内存中。这就是闭包的“记忆效应”。
function outer() {
let a = 1; // 外部函数的局部变量
return function inner() { // 内部函数
console.log(a); // 访问了外部函数的变量
}
}
const fn = outer(); // outer 执行完毕,按理说 a 应该销毁
fn(); // 输出 1,a 依然存在,这就是闭包
柯里化与偏函数
这是函数式编程的基础。利用闭包预先设置一些参数,生成一个新的函数。
场景: 封装通用的请求函数。
function makeRequest(baseURL) {
// baseURL 被闭包记住了
return function(path, params) {
console.log(`请求地址: ${baseURL}${path}`, params);
// 实际发送 fetch 请求...
}
}
const requestLocal = makeRequest('http://localhost:3000');
const requestOnline = makeRequest('https://api.production.com');
// 后续调用非常简洁
requestLocal('/user', {id: 1}); // 请求地址: http://localhost:3000/user
requestOnline('/order', {id: 2}); // 请求地址: https://api.production.com/order