zoukankan      html  css  js  c++  java
  • js 闭包原理

    闭包的定义:闭包是指有权访问另一个函数作用域中的变量的函数  --《JavaScript 高级程序设计》。

    如何理解这句话:其实就是指在函数a外面能够访问函数a里面的函数b

    例如:

     1 function a () {
     2   var v = 123;
     3   function b() {
     4     console.log(v);
     5   }
     6   return b;
     7 }
     8 
     9 var b = a();
    10 b();  // 123

    执行函数a时把函数b返回,此时函数b就保存到了a的外面,这时候就可以在a函数的外部对b进行访问。

    相关知识点:js作用域链

    执行原理:

    1、首先在预编译全局代码时,生成GO

      GO {

        a: function a() {...},

        b: undefined

      }

    2、执行 var b = a();  此时对a函数进行预编译并创建a 函数的AO 

      AO {

        v: undefined,

        a: undefined,

        b: function b() {...}

      }

    3、创建a函数的作用域链

      a.[[Scopes]] = [AO, GO];  

    4、由于函数的提升,会在a函数进行预编译的时候创建b函数的AO

      b  AO {}

      b.[[Scopes]] = [AO(b), AO(a), GO]

    5、执行 var v = 123;  在js预编译中提到由于var v 的声明已经得到了提升,所以此时只执行v = 123;对AO里的v 进行赋值。

      AO {

        v: 123,

        a: undefined,

        b: function b() {...}

      }

    6、之后将函数b返回,此时a函数执行完毕,a函数对应的AO理应销毁,但是由于在b函数中又对a函数的AO中的变量进行应用,所以a函数的AO不能被垃圾回收机制销毁,但是会跟a函数断开联系,当a函数再次执行,会重新创建一个a函数的AO。

    7、在全局变量中使用b 接收函数a的返回,此时GO变为

      GO {

        a: function a() {...},

        b: function b() {...}

      }

     

    8、全局里的b

      在b函数中打印v变量,由于b函数的AO中没有v变量,所以顺着作用域链往上找,在a的AO中找到v并打印。

    闭包优缺点:

      优点:

        1、属性的私有化,在b返回后,处理b函数中能对v进行操作,其它地方都不能对v进行操作。

        2、防止变量污染。

      缺点:

        容易造成内存泄漏,因为如果后期不对全局中的b进行处理(例如:赋值为null),a函数的AO 会一直存在于内存中,如果多次调用a函数,容易导致内存中的垃圾数据越来越多造成内存泄漏。

  • 相关阅读:
    【链接】idea没有svn
    移动端适配解决方案
    项目中多个文件引入同一份公共样式less文件导致编译打包后有多份样式
    2020最新编辑器集成eslint、prettier、stylelint,git提交预检查代码配置
    eslint+prettier学习
    artTempate模版继承父模版之后再引入子模版不生效?
    iOS底层原理开篇
    iOS应用千万级架构:安全与加密
    使用RabbitMQ实现延迟任务
    JAVA三元运算符空指针引用的坑
  • 原文地址:https://www.cnblogs.com/linyabin/p/12375510.html
Copyright © 2011-2022 走看看