什么是闭包?

  1. let outer = 100
  2. function cons(){
  3. console.log(outer)
  4. }
  1. cons()//100

像这样在 一个作用域内部可以访问到外部的变量 就形成了闭包 so easy

闭包的作用?

实现持久化封装

它可以将一个属性私有化,并且持久化
也就是说,我不希望这个属性被随意访问或者修改,或者我们需要保存一个状态的时候
实现

  1. function store(){
  2. let money = 100;
  3. set = function(num){
  4. money = money+num;
  5. return money
  6. }
  7. get =function (num){
  8. money = money-num;
  9. return money
  10. }
  11. return {
  12. getmoney:get,
  13. setmoney:set
  14. }
  15. }
  1. let s = store()
  2. s.getmoney(10)
  3. 90
  4. s.setmoney(10)
  5. 100
  6. s.setmoney(10)
  7. 110
  8. s.setmoney(10)
  9. 120

应用场景

节流和防抖

节流是让多次触发的事件在固定时间段内执行一次
所以需要使用闭包去记录这个事件,在固定时间去执行

防抖是让多次触发的事件只执行最后一次
所以需要使用闭包去记录这个时间,在这个时间段内没有被触发后执行
移步代码

setTimeout

  1. for(var i = 1; i <= 5; i ++){
  2. setTimeout(function timer(){
  3. console.log(i)
  4. }, 0)
  5. }

执行结果

  1. 5.6

一次性打印了5次6
代码先执行了for循环,每次把function timer(){console.log(i) } 放入循环队列,所以执行时间几乎是一致的

使用let

  1. for (let i = 0; i < 5; i++) {
  2. setTimeout(function() {
  3. console.log(Date.now(), i);
  4. }, 1000);
  5. }

执行结果

  1. VM176:3 1638585229265 0
  2. VM176:3 1638585229266 1
  3. VM176:3 1638585229266 2
  4. VM176:3 1638585229266 3
  5. VM176:3 1638585229266 4

使用闭包

  1. for (var i = 0; i < 5; i++) {
  2. (function(j){
  3. setTimeout(function() {
  4. console.log(Date.now(), j);
  5. }, 1000)
  6. })(i)
  7. }

执行结果一样是同时执行

  1. 1638585514966 0
  2. 1638585514967 1
  3. 1638585514967 2
  4. 1638585514967 3
  5. 1638585514967 4

按秒输出

  1. for (var i = 0; i < 5; i++) {
  2. (function(j) {
  3. setTimeout(function() {
  4. console.log(Date.now(), j);
  5. }, 1000 * j); // 这里修改 0~4 的定时器时间
  6. })(i);
  7. }
  8. for (let i = 0; i < 5; i++) {
  9. setTimeout(function() {
  10. console.log(Date.now(), i);
  11. }, 1000*i);
  12. }

使用promise

  1. const sleep = (timeountMS) => new Promise((resolve) => {
  2. setTimeout(resolve, timeountMS);
  3. });
  4. (async () => { // 声明即执行的 async 函数表达式
  5. for (var i = 0; i < 5; i++) {
  6. if (i > 0) {
  7. await sleep(1000);
  8. }
  9. console.log(new Date, i);
  10. }
  11. await sleep(1000);
  12. console.log(new Date, i);
  13. })();

闭包要思考的问题?

闭包的内存泄露?

闭包没有内存泄露的问题,常驻内存的原因是外部对闭包的引用,而非闭包内部变量的引用,内存无法释放是IE的bug

使用闭包?

我们在开发时是先有需求,然后想到使用闭包,而不是代码恰好形成了闭包而使用。