欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

js 闭包原理

程序员文章站 2022-06-25 08:36:17
闭包的定义:闭包是指有权访问另一个函数作用域中的变量的函数 --《JavaScript 高级程序设计》。 如何理解这句话:其实就是指在函数a外面能够访问函数a里面的函数b。 例如: 1 function a () { 2 var v = 123; 3 function b() { 4 console ......

闭包的定义:闭包是指有权访问另一个函数作用域中的变量的函数  --《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进行访问。

 

相关知识点:

执行原理:

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函数,容易导致内存中的垃圾数据越来越多造成内存泄漏。