关于闭包的理解(JS学习小结)

前言:css

啊啊啊,看书真的很痛苦啊,仍是好想作项目写代码才有意思,不过我如今缺的确是将知识体系化,因此不论看书多么痛苦都必定要坚持坚持啊,这才是我如今最须要的进步的地方,加油!前端

由于如今期末啦,下周一也就是明天开始就有考试,因此复习是主要的事情,看书的速度比较慢了,一周大概也就184页(P110-P284), 虽然页数比较少可是其中有ES中很是最重要的两个概念——原型链闭包,以前对于两个知识的了解算是知其然不知其因此然的,因此在那两章我也有意多花费了时间,确保我可以吃透这个概念。如下算是我本身的一些理解,若是有不很正确的地方,但愿大神们多多指教,康桑阿米达~编程

哦,对了,我看的JS书是《Javascript 高级程序设计(第3版)》,若是有正在看这本书的小伙伴能够一块儿哇~你们多多交流,互相学习嘛~闭包

 

正文:编程语言

如今最流行的编程语言里面必定有“对象”的概念,咱们的第一节实验课老师就叫咱们怎么找对象,因此可见对象对于程序猿的重要性,因此你有对象了嘛?:) 那这世界上对象千千万,咱们怎么知道哪一个对象合适呢?总不能一个一个的相处试试看吧?好在咱们发现不少对象都有类似之处,因此咱们将他们类似的部分抽象出来,造成了一个全新的概念,在咱们须要的时候,比对咱们的须要和这个概念,再进行选择,就会节省咱们不少功夫并更好更快的得到咱们想要的结果。而这个概念在JS中就是引用类型,Object(JS中没有类的概念,若是学过C++或者Java、C#等语言的,那也会很容易就对应get到JS中引用类型的)。Object确实是JS中很是强大的部分,但却不是最有意思的,那最有意思的是什么?Function。函数

在JS中,Function也是一个Object的一个对象。而关于这个概念的延伸,像是继承、原型链等等就又能够再开一把了,若是实在是饥渴难耐的,那就快去搜索大神们博客或者找一本《JavaScript高级程序设计》和我一块儿学习啦~因此,咱们如今就将矛头对准,闭包!开火,嘣嘣嘣嘣学习

在说闭包的概念以前,咱们总得知道这个名词究竟是什么意思吧?spa

因此什么是闭包?函数。设计

既然就是函数为何又特别要取个名字?它到底特别在哪?code

可以访问另外一个函数做用域中的变量。(此处的做用域姑且理解为{}以内)

For example,上个例子就知道了,不要问我例子是谁

function outerFunc(arg){

   return function innerFunc(){
        alert(arg);
    }  

}

此处名为outerFunc的函数返回了一个名为innerFunc函数,这个函数在内部只有一句“alert(arg);”,但是运用技能一眼看穿法,找不到arg,再往上,哇哦,在outerFunc的参数那找到了呢,真开心。因此这个innerFunc(函数)访问了outerFunc(另外一个函数)做用域内(在outerFunc的{}中,但没在innerFunc的{}中)的变量(arg),因此这个innerFunc就是一个闭包。(大多数时候,不会为闭包命名,此处只为更好的说明。)

OK,闭包的概念知道啦,那如何造成闭包这个现象的呢?显然刚刚别有深意,欲拒还迎的做用域使的小把戏啦,别怕,咱们立马拿下。

“当某个函数被调用时,会建立一个执行环境及相应的做用域链。”

“每一个执行环境都有一个表示变量的对象——变量对象。(variable object)。”

固然仍是要先名词解释,要是都不知道这个名词指的什么,那还怎么玩。

做用域:也就是变量对象的别称。

做用域链:就是做用域呗。一条把做用域像腊肉穿起来的子。它只是一条链子因此做用域链就只保存着变量对象地址,而不是变量对象自己。

执行环境执行环境指向本身独有的做用域链做用域链又按照当前函数做用域,外部函数做用域,外部函数的外部函数做用域....直至全局做用域。

再来了解了解,咱们写了个函数而后调用它实现了功能,那JS到底又为此作了什么。
(1)在建立函数时,会建立一个预先包含全局变量对象的做用域链,保存在内部的属性[[scope]]中。
(2)当调用函数时,会为函数建立一个执行环境,而后经过复制函数的[[scope]]属性,构建起执行环境的做用域链。
(3)建立一个活动对象(此处即变量对象)放在执行环境做用域链的最前端。
而当函数在访问一个变量的时候,即在innerFunc函数的执行环境中执行到“alert(arg);”时,执行环境找到本身的做用域链小伙伴,而后做用域链说没问题,我帮你问问个人做用域兄弟们,而后做用域链就问innerFunc()做用域,“你好,请问你有arg这个变量吗?”“很差意思,我没有呢。”“不要紧哦。谢谢你。”“不客气。”(老师教导咱们要作一个有礼貌的好孩子。)而后它又问outerFunc()做用域,“请问你有arg这个变量吗?”“我有哦。”ok,皆大欢喜,找到了arg,顺利执行了“alert(arg);”语句,不然一直到全局做用域依然没有找到的话,就只能报错了呢。
通常讲,函数执行完毕,那就销毁吧。可是,闭包就这么被销毁了,哪里对得起它特别的名字呢?
 1 function outerFunc(arg){
 2 
 3    return function innerFunc(){
 4         alert(arg);
 5     }  
 6 
 7 }
 8 
 9 var result = outerFunc(1); //返回innerFunc函数
10 result();                  //输出1

 

仍是刚才的函数,仍是原来的配方,再加点料,看看效果。

按照刚刚说的,outerFunc在第9行执行完毕后,应该就被销毁了(事实上也是如此),但为什么第10行的执行依然可以成功呢?聪明的你必定知道啦,做用域和做用域链的关系。outerFunc在第9行执行后,outerFunc的执行环境和做用域链都被销毁,可是!innerFunc的做用域链还在对innerFunc做用域和outerFunc做用域进行引用。也就是所谓了“引用计数不惟一”。因此,尽管outerFunc已经被销毁,可是innerFunc依然可以访问到arg变量的值啦。
因此你看闭包并无很难嘛,不用怕它,固然我在此说的,都是简单的初级概念,闭包的运用就像是css中的浮动的运用同样,知道概念是很容易的事情,可是真的运用驾轻就熟确实是很是高段位的事了,因此一块儿加油咯~
 
后话:
明天考试英语,但愿能考好啊,我要求不高,上90就行啊。(强行装逼,没必要理我)
相关文章
相关标签/搜索