什么是闭包?
let outer = 100function 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)90s.setmoney(10)100s.setmoney(10)110s.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 0VM176:3 1638585229266 1VM176:3 1638585229266 2VM176:3 1638585229266 3VM176:3 1638585229266 4
使用闭包
for (var i = 0; i < 5; i++) {(function(j){setTimeout(function() {console.log(Date.now(), j);}, 1000)})(i)}
执行结果一样是同时执行
1638585514966 01638585514967 11638585514967 21638585514967 31638585514967 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
使用闭包?
我们在开发时是先有需求,然后想到使用闭包,而不是代码恰好形成了闭包而使用。
