家人们,今天咱来聊聊JavaScript里的闭包,这可是面试高频考点,面试官老爱问“JS闭包为什么不会被销毁”,好多小伙伴都被问懵了,别慌,今天咱就把它吃透!
先给大伙讲个生活里的例子来理解闭包。你就把自己想象成一个大厨,你有一个专属的厨房(这就是一个函数作用域)。厨房里有各种各样的食材(变量),你在这个厨房里做了一道超美味的蛋糕(执行函数)。正常情况下,你做完蛋糕,厨房就清理干净了,食材也都收起来了(函数执行完,变量就被销毁了)。
但是呢,你有个特别好的朋友,你给了他厨房的备用钥匙(返回一个内部函数引用),他随时可以进来拿食材做点小点心。因为他有钥匙,所以厨房不能被完全清理掉,食材也得留着,不然朋友来了没东西可用。这就是闭包,即使外部函数执行完了,内部函数因为被引用着,所以它所依赖的变量和环境也不会被销毁。
闭包因保持对外部作用域变量的引用而具备可达性,所以不会被销毁
代码里的闭包长啥样?
function outerFunction() {
let outerVariable = 10; // 这就是厨房里的食材,外部函数的变量
function innerFunction() {
console.log(outerVariable); // 内部函数使用了外部函数的变量
return outerVariable;
}
return innerFunction;
}
let closureFunction = outerFunction(); // 拿到厨房钥匙,调用外部函数,返回内部函数
closureFunction(); // 用钥匙进入厨房,执行内部函数,此时outerVariable不会被销毁
在这段代码里,outerFunction就是那个厨房,outerVariable是食材,innerFunction是你给朋友的钥匙。当outerFunction执行完,正常来说outerVariable应该被销毁,但因为innerFunction引用了它,所以它还留在内存里。
实际开发场景中的闭包
1. 数据隐私保护
假设你在开发一个用户信息管理系统,每个用户都有自己的敏感信息,像密码啥的。你不想让外部随意访问和修改这些信息,就可以用闭包来实现数据的隐私保护。
function userInfo() {
let password = "123456"; // 敏感信息,相当于厨房的秘密食材
return {
getPassword: function () {
return password; // 给你一个获取密码的小窗口,只能看不能改
},
updatePassword: function (newPassword) {
if (newPassword.length >= 6) {
password = newPassword;
console.log('密码已更新');
} else {
console.log('新密码长度不足');
}
}
};
}
let user = userInfo();
console.log(user.getPassword()); // 可以获取密码
user.updatePassword("new123456"); // 可以更新密码
这里,password变量被闭包保护起来,外部无法直接访问和修改,只能通过getPassword和updatePassword这两个函数来操作,就像给敏感信息上了一把锁。
2. 事件绑定和回调
再比如,你在做一个网页小游戏,有个按钮,点击按钮会触发一个动画效果。你想在按钮点击事件里使用一些局部变量,又不想这些变量在其他地方被随意修改,闭包就派上用场了。
function game() {
let score = 0; // 玩家的分数,游戏里的小秘密
let button = document.createElement('button');
button.textContent = '点击加分';
document.body.appendChild(button);
button.onclick = function () {
score++;
console.log('当前分数:', score);
};
}
game();
在这个例子里,score变量在game函数内部,通过闭包,它在按钮点击事件回调函数里也能被访问和修改,而且其他代码无法直接接触到score,保证了游戏逻辑的独立性和安全性。
3. 函数柯里化
函数柯里化也是闭包的一个经典应用场景。比如说你在做一个电商项目,需要计算商品的总价,不同商品有不同的折扣。
function calculateTotal(discount) {
return function (price, quantity) {
return price * quantity * (1 - discount);
};
}
let calculateWithTenPercentDiscount = calculateTotal(0.1); // 先设置好折扣
let total = calculateWithTenPercentDiscount(100, 5); // 再计算总价
console.log('折扣后的总价:', total);
这里calculateTotal返回一个新的函数,这个新函数记住了discount参数,就像一个小账本,下次计算总价的时候直接用就行,这就是闭包在函数柯里化里的作用。
家人们,这下知道JS闭包为啥不会被销毁了吧!它在实际开发中用处可大了,数据隐私保护、事件绑定、函数柯里化等等都能看到它的身影。下次面试官再问,咱就把这些例子甩出去,妥妥的!要是大伙在学习闭包的时候还有啥疑问,或者有好玩的闭包应用场景,都来评论区唠唠!