JS 闭包

先来看个题目

话说有个函数如下

function a(){
  let aa = 0;
  function b(){
      aa ++;
      console.log(aa);
  }
  return b;
}

我们调用方式如下

//方式一:直接连续调用
a()(); //1
a()(); //1

//方式二:赋值之后再调用
const fn=a();
fn(); // 1
fn(); // 2

解释一下,第一种调用方式没有形成闭包,所以aa在a调用完成时就已经被销毁了。
第二种调用方式作用域转移到了fn上,所以aa并没有随着a的调用完成而销毁,所以第二次输出会在前一次。

由以上例子可以证明闭包的存在条件,

  1. 作用域嵌套,返回一个作用域,例如一个函数中返回另一个函数
  2. 作用域转移,然后再调用,例如外部函数赋值新变量,执行新变量

我们对上面题目继续进行变化一下

  1. 变形一:
function a(){
  let aa = 0;
  console.log(aa);
  function b(){
      aa ++;
  }
  return b;
}

//调用
const fn=a();
fn();
fn();
fn();

我们查看控制台打印出什么?,只打印出一个0,调用三次fn只打印出一个0?是的,没错。因为fn每次调用的是b这个函数,a只执行了一次。

  1. 变形二:
let i=0;
function a(){
  i++;
  console.log(i);
}

//调用
const fn = a;
fn(); //1
fn(); //2

如果写成如上形式,那么它是一个闭包吗?答案肯定不是的,

  1. 变形三:
function a(){
  let aa = 0;

  function b(){
      aa ++;
      console.log(aa);
  }
  return b();
}

// 调用 
const fn = a;
fn(); //1
fn(); //1

如果写成这样,也不会形成闭包,b在return 之前已经执行完成了

闭包是什么

函数(局部)作用域转移,该作用域下的变量也跟着转移,导致相关变量不被销毁常驻内存。
函数里return另一个函数,调用之时进行赋值转移。类似如下结构

function func1(){
  return function func2(){
    //you code
  }
}
const func3=func1();

工作中使用闭包的情况

  1. 防抖和节流
  2. 较大作用域中修改较小作用域中变量的值,私有属性

参考

原文地址:https://www.cnblogs.com/xingguozhiming/p/13466234.html