什么是闭包?
let outer = 100
function cons(){
console.log(outer)
}
cons()//100
像这样在 一个作用域内部可以访问到外部的变量 就形成了闭包 so easy
闭包的作用?
实现持久化封装
它可以将一个属性私有化,并且持久化
也就是说,我不希望这个属性被随意访问或者修改,或者我们需要保存一个状态的时候
实现
function store(){
let money = 100;
set = function(num){
money = money+num;
return money
}
get =function (num){
money = money-num;
return money
}
return {
getmoney:get,
setmoney:set
}
}
let s = store()
s.getmoney(10)
90
s.setmoney(10)
100
s.setmoney(10)
110
s.setmoney(10)
120
应用场景
节流和防抖
节流是让多次触发的事件在固定时间段内执行一次
所以需要使用闭包去记录这个事件,在固定时间去执行
防抖是让多次触发的事件只执行最后一次
所以需要使用闭包去记录这个时间,在这个时间段内没有被触发后执行
移步代码
setTimeout
for(var i = 1; i <= 5; i ++){
setTimeout(function timer(){
console.log(i)
}, 0)
}
执行结果
5.6
一次性打印了5次6
代码先执行了for循环,每次把function timer(){console.log(i) } 放入循环队列,所以执行时间几乎是一致的
使用let
for (let i = 0; i < 5; i++) {
setTimeout(function() {
console.log(Date.now(), i);
}, 1000);
}
执行结果
VM176:3 1638585229265 0
VM176:3 1638585229266 1
VM176:3 1638585229266 2
VM176:3 1638585229266 3
VM176:3 1638585229266 4
使用闭包
for (var i = 0; i < 5; i++) {
(function(j){
setTimeout(function() {
console.log(Date.now(), j);
}, 1000)
})(i)
}
执行结果一样是同时执行
1638585514966 0
1638585514967 1
1638585514967 2
1638585514967 3
1638585514967 4
按秒输出
for (var i = 0; i < 5; i++) {
(function(j) {
setTimeout(function() {
console.log(Date.now(), j);
}, 1000 * j); // 这里修改 0~4 的定时器时间
})(i);
}
或
for (let i = 0; i < 5; i++) {
setTimeout(function() {
console.log(Date.now(), i);
}, 1000*i);
}
使用promise
const sleep = (timeountMS) => new Promise((resolve) => {
setTimeout(resolve, timeountMS);
});
(async () => { // 声明即执行的 async 函数表达式
for (var i = 0; i < 5; i++) {
if (i > 0) {
await sleep(1000);
}
console.log(new Date, i);
}
await sleep(1000);
console.log(new Date, i);
})();
闭包要思考的问题?
闭包的内存泄露?
闭包没有内存泄露的问题,常驻内存的原因是外部对闭包的引用,而非闭包内部变量的引用,内存无法释放是IE的bug
使用闭包?
我们在开发时是先有需求,然后想到使用闭包,而不是代码恰好形成了闭包而使用。