js闭包的原理

什么是闭包

从作用上说:既能重用一个变量,又能保护变量不会被全局污染的一种编程方式

闭包的本质/原理

外层函数的作用域对象,被内层函数引用着无法释放,就形成闭包对象

要理解上面这两句话首先我们来看一个小例子

<script>
      var a = 100;
      function fun() {
        a = 200;
        a++;
        console.log(a);
      }
      fun();
      console.log(a);
</script>

这个例子输出的结果是什么呢?以上面的例子来分析代码执行的过程

  1. 当浏览器开始扫描时,这时候还没有执行代码。只是先声明变量,将变量先存储在window对象中(可打印一下console.log(window)看一看里面的变量)
    在这里插入图片描述
    代码执行后,函数会自动创建临时函数作用域对象
    在这里插入图片描述
    当代码执行完成后,会把临时创建的函数作用域对象给清空
    在这里插入图片描述
    所以函数中的a是全局的变量a,所以两次打印出来的值都是201。那如果把上面的例子改成下面的代码会怎么样呢?
var a = 100;
      function fun() {
        var a = 200;
        a++;
        console.log(a);
      }
      fun();
      console.log(a);

这个例子输出的结果是两次201吗?我们来输出看一看
在这里插入图片描述
这为什么两次的输出不同呢?因为函数里面声明了一个a变量,在函数里面声明的变量会存在临时创建的函数作用域对象中,函数内部的变量a会先去临时创建的函数作用域对象中查找,找到有a变量就拿函数作用域对象的变量来赋值,就不会去到window对象中找变量a,所以window对象中的a变量不受影响。
在这里插入图片描述
到代码执行结束后临时创建的函数作用域对象就会被回收,所以函数中的答打印是201,函数外的a变量没有受到影响所以还是100
在这里插入图片描述
所以得出结论

1.使用全局变量:可以被重复使用,但是极易被污染和篡改。
2.使用局部变量:只能在函数内使用,出了函数用不了,绝对不会被篡改,但是不能重用。

那我想我的变量不被全局给污染和篡改又能重用应该怎么办?
这时候就要用到最上面闭包了,使用闭包就能实现这个需求,那闭包如何使用呢?看下面的例子

<script>
      //需求: 定义一个函数为小孩儿管理压岁钱
      //  小孩儿每花一笔钱,可以从总钱数中扣除花的钱,提示还剩xxx
      //1. 定义一个外层函数,包裹要保护的变量和内层函数
      function parent() {
        var total = 1000;
        //2. 外层函数将内层函数对象返回到函数外部,让外部可用
        //不用给内层函数起名字
        return function (money) {
          //小孩儿 //局部
          total -= money;
          console.log(`花了${money}, 还剩${total}`);
        };
      }
      //3. 想用内层函数的人需要调用外层函数,才能获得返回出来的内层函数,保存在变量中,反复使用。
      var pay = parent();
      total = 0; //试图篡改total变量 结果total不能被篡改
      pay(100); //花了100, 还剩900
      pay(100); //花了100, 还剩800
      pay(100); //花了100, 还剩700

      var pay1 = parent();
      pay1(100); //重新形成一个闭包 花了100, 还剩900
</script>

看看输出结果
在这里插入图片描述
闭包的形成如下图
在parent函数正在被调用的那瞬间,就会创建一个临时函数作用域对象
在这里插入图片描述
然后调parent后,由于pay一直引用这parent创建的临时函数作用域,导致这个临时创建出来的函数作用域无法被释放,而形成了闭包
在这里插入图片描述
总结成一句话

外层函数的作用域对象,被内层函数引用着无法释放,就形成闭包对象

闭包的缺点

比一般的函数多占用一块内存空间——多占外层函数的作用域对象

如何解决这个缺点呢?以上面的例子来说,如果pay不用到了,就将把pay = null,释放掉函数作用对象。这样就不会多占外层函数的作用域对象

这是我个人对闭包的理解,如果说得不好请多多指教。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值