JS(七)闭包

作者 : 开心源码 本文共1448个字,预计阅读时间需要4分钟 发布时间: 2022-05-13 共158人阅读

1.什么是闭包?

《JavaScript高级程序设计》这样形容:

闭包是指有权访问另一个函数作用域中的变量的函数;

《JavaScript权威指南》这样形容:

函数对象可以通过作用域链相互关联起来,函数体内部的变量都可以保存在函数作用域中,这种特性在计算机科学文献中被称为‘闭包’
从技术的角度讲,所有的JavaScript函数都是闭包:它们都是对象,它们都关联到作用域链。

MDN中这样说:

闭包是函数和公告该函数的词法环境的组合

《你不知道的JavaScript》这样形容:

当函数可以记住并访问所在的词法作用域时,就产生了闭包,即便函数是在当前词法作用域之外执行。

最后一种说法在我浏览各种关于闭包的了解时,出现的最为频繁,也较为易懂。

词法作用域是由函数公告时书写代码的位置决定的,而闭包是词法作用域形成的自然结果。当在函数内部公告了内部函数,并将内部函数作为值返回,就会产生闭包。

function fn1() {    var name = 'Tilo';    function fn2() {        console.log(name);    }    return fn2;}var fn3 = fn1();fn3();

注:在这个代码中,我们假如直接在全局作用域下调用fn2函数,就会报错ReferenceError,这是跟作用域判断有关,由于引擎首先会根据词法作用域的查询规则RHS。

在作用域中查找变量都是RHS,并且查找的规则是从当前作用域开始找,假如没找到再到父级作用域中找,一层层往外找,假如在全局作用域假如还没找到的话,就会报错了:ReferenceError: 某变量 is not defined。

将内部函数作为值传递并且return,在调用了fn1函数之后,fn2函数会保持对fn1的词法作用域的引用,记住并可以访问所在的词法作用域(这里就是fn1的作用域)。看到一位老师的比喻,讲说:将函数作为值传递,实际就是打开了一条访问内部变量的通道。这‘通道’说的就是内部函数对词法作用域的引用,这个引用就是闭包。

换言之,当fn1函数执行完毕之后,其作用域是会被销毁的,而后垃圾回收器会释放那段内存空间。而闭包却很神奇的将fn1的作用域存活下来,fn2仍然持有该作用域的引用,这个引用就是闭包。

总结:某个函数在定义时的词法作用域之外的地方被调用,闭包可以使该函数继续访问定义时的词法作用域。

2.闭包的特点

①基于词法作用域的查找规则。

②在一个函数内部定义一个内部函数,而后将内部函数作为值返回,或者者直接或者者间接的立即执行内部函数。

③拥有更长的生命周期,保持对当前词法作用域的引用。

?函数作为值返回

function fn1() {    var num = 23;    function fn2() {        return num;    }    return fn2;}var fn3 = fn1();console.log(fn3()); //23

正常情况下,fn1函数执行之后,在JS中fn1函数的作用域就被销毁,内存空间被释放,由于这里将函数作为值返回了,产生了闭包,由于闭包的作用,我们依然可以在局部作用域里访问到num,所以fn1的的词法作用域依然存在,证实了闭包可以访问所在的词法作用域,且拥有更长的生命周期,保持对当前词法作用域的引用。

?直接或者间接的执行内部函数

function fn1(){   var num = 20;   function fn2(){      console.log(num)   }   fn2();}fn1() ; //20

上面代码中,一样形成了闭包。并且产生的结果与第一种情况相同。

参考凯斯老师在什么是闭包?中的答复,侵删。

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » JS(七)闭包

发表回复