关于闭包

理解闭包之前,需要先了解函数作用域,作用域链,垃圾回收机制

一、函数作用域

闭包在《权威指南》,第8章函数这一章进行了讲解,在《你所不知道的js》同样也是放在讲解了作用域之后的第一部分第5章,来讲解闭包。

《你所不知道的js》讲解闭包这一章的名字值得深思——作用域闭包,从这个名字应该就能猜到,闭包与函数作用域密不可分。

函数作用域:在函数内声明的所有变量可以在函数体内被查找到,也可以被该函数嵌套的任何函数体内查找这些变量。

查找规则是:从运行时所处的作用域开始,由内而外,逐级向外查找。

如图1区域声明的变量为全局变量,_i在整个2区域都可被查找到。c_fnc被调用时,在3区域没有找到变量_i,转而在2区域查找,并且找到了这个变量,然后做输出处理。

二、作用域链

上一节说到,变量的查找遵循由内而外,逐级查找的规则。这些逐级查找的一系列对象就存在于作用链上。

2.1.什么是作用域链

作用域链是一个对象列表。不如变量x查找时,从链上的第一个对象开始查找这个对象是否有一个x属性,依次查找每个对象,如果找到就用这个对象的x的值,如果作用域链上所有对象都查找完成都没有找到,会抛出引用错误异常。

比如:

上面是一段不包含任何函数定义的代码,这段代码运行时与之关联的作用域上只有一个全局对象。

函数foo调用时,与foo函数关联的作用域链上有2个对象,第一个对象是包含foo函数内部_c的局部变量,第二个是全局对象。

2.2 作用域链是什么时候存在的?

在函数调用时,就会生成一条作用域链,并且被保存。

函数调用时,会创建一个新的对象(也可以理解为创建了一个活动记录或者执行上下文)。

这个新的对象包含:

2.3 示例代码:

上面代码作用域链图解如下:

三、垃圾回收机制

3.1、概述

c语言中,在内存使用完成后需要程序员手动释放内存。js中提供了自动内存管理的能力,减轻了程序员这部分的工作量。

主要通过引用计数的方法找到不再使用的内存,被引擎释放掉,这就是垃圾回收机制。

在2.3的代码中,foo()执行完成后,新创建的第一个对象,由于不存在其他变量对它的引用,所以函数foo被执行完成后,第一个对象会被从作用域中删除(垃圾回收)。

第一个对象里包含的局部变量_c和作用域链foo_child也会随之被删除。

在foo函数体外部再想得到foo函数局部变量_c已然不可能。

3.2、影响

内存不能及时释放,造成内存泄露

四、闭包

由垃圾回收机制可知,只要想办法在foo函数执行完成后,依然保留foo函数作用域链的第一个对象就能将局部变量_c保留下来。

由第一部分作用域可知,js遵循词法作用域,函数体内的子函数可以获取父函数的变量。

实例代码:

function foo(){
    let _c = "Aphelios";
    function foo_child(){
      let _a="Tresh";
      console.log(_a + "---"+_c);
    }
    return foo_child;
}
var result=foo();
result();//"Tresh---Aphelios"

变量引用图解:

在上述图中,foo函数执行完成后,返回了一个函数,被保存在全局变量result上。外部变量result指向子函数foo_child,foo_child又存在对父函数局部变量_c的引用。

这样包含局部变量_c的第一个对象就不会被垃圾回收(即第一个红框)。

result拉着foo_child,foo_child又拉着_c,_c又是新对象的一个属性。新对象不能被垃圾回收。

这样,即使foo函数执行完成,依然能在foo函数体外通过闭包,获取它的局部变量。

五、总结

父函数(foo)执行时,本来父函数的局部变量(_c)只能在父函数体内或者嵌套函数体内被查找到,在父函数执行完成后,父函数的局部变量应该被垃圾回收,不再存在内存中。但是由于闭包的存在,使得父函数执行完成后,父函数体外存在变量(result)对嵌套函数(foo_child)的引用,嵌套函数(foo_child)不会被垃圾回收,嵌套函数体内变量绑定的对象(第4部分图中的第一个对象)也不会被垃圾回收。

以上,后续会在继续完善内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值