最近朋友几篇文章介绍了改作用域链的文章. 关联文章的地址
读《JavaScript高等程序设计》第7章有感。
一、究竟闭包是什么?
闭包是指有权拜访另一个函数作用域中的变量的函数。
个人感悟:
通过书中的这句定义,按中文语法分析,说白了,闭包就是一种函数,而这种函数可以拜访另一个函数作用域中的变量。
那为什么这种函数有这样牛B的功能呢?其实,它是利用了函数的作用域链。
二、创建闭包的罕见方式:在一个函数外部创建另一个函数
function createComparisonFunction(propertyName){ return function(object1,object2){ var value1 = object1[propertyName]; var value2 = object2[propertyName]; if(value1 < value2){ return -1; }else if(value1 > value2){ return 1; }else{ return 0; } }; }
这两行代码拜访了外部函数中的变量propertyName。即使这个外部函数被返回了,而且是在其他地方被调用了,但它仍然可以拜访变量propertyName。
之所以还可以拜访这个变量,是因为这个匿名函数的作用域链中包含了createComparisonFunction()的作用域(在作用域链中是以变量对象表示)
三、闭包可以起什么作用?为什么闭包可以起作用?
说到这里,我们不得不回忆一下之前学过的关于作用域链的知识。只有透彻懂得作用域链,才能真正懂得闭包起什么作用,为什么可以起作用。
关于作用域链的知识,在我上一篇博文中已详细说明,在这就不重复叙说了,我只讲症结的地方。
首先,当调用某个函数的时候,系统会为函数创建一个执行环境,并且通过复制函数的[[Scope]]属性中的对象构建起执行环境的作用域链。而函数的活动对象作为变量对象被推入执行环境作用域链的最前端。
可见,当函数被调用时,会创建两个货色,一个是函数的执行环境,另一个则是其相应的作用域链。
一般来说,当函数执行完毕后,局部活动对象就会被销毁,内存中仅保存全局作用域(也就是全局执行环境的变量对象)。
但是,闭包的情况有所不同。原因就是:
在另一个函数外部定义的函数会将包含函数(即外部函数)的活动对象添加到它的作用域链中。
回到下面的例子:
function createComparisonFunction(propertyName){ return function(object1,object2){ var value1 = object1[propertyName]; var value2 = object2[propertyName]; if(value1 < value2){ return -1; }else if(value1 > value2){ return 1; }else{ return 0; } }; }
在匿名函数从createComparisonFunction()中被返回后,它的作用域链就变成了下图所示:
此时,匿名函数可以拜访在createComparisonFunction()中定义的所有变量。
更重要的是,当createComparisonFunction()函数执行完毕后,也就是返回了匿名函数后,它的活动对象也不会被销毁,这是因为匿名函数的作用域链仍然在引用这个活动对象。
也就是说,当createComparisonFunction()函数返回后,它的执行环境的作用域链会被销毁,但它的活动对象仍然被引用。根据JS的GC策略,因为该活动对象引用次数不为0,因此它会留在内存中,直到匿名函数被销毁后,createComparisonFunction()的活动对象才会被销毁。
四、闭包与变量
由上知,闭包是通过作用域链这种机制来实现的,因此,它也有着一个值得我们注意的副作用,那就是:
闭包只能获得包含函数中任何变量的最后一个值,因为闭包只是引用其作用域链上的变量对象。
例子不敲了,自己推敲一下吧哈~书上有,懒得敲了。
五、总结
由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存,过度应用闭包可能会致使内存占用过多,这方面要注意一下。
这本JS基本书至心好,闭包这部分得多看看。
关于闭包的一些应用将在下一篇文章报告。
共勉。
文章结束给大家分享下程序员的一些笑话语录: 有一天,一个男人穿越森林的时候,听到一个细微的声音叫住他。他低头一看,是一只青蛙。
“如果你亲我一下,我会变成一个美丽的公主哦。”男人一言不发,把青蛙捡起来,放入口袋。
“如果你亲我一下,我会变成一个美丽的公主哦。而且,我会告诉我遇到的每一个人,你是多么聪明和勇敢,你是我的英雄。”男人把青蛙拿出来,对着它微微一笑,又把它放回口袋。
“如果你亲我一下,我会变成一个美丽的公主,然后我愿意成为你的爱人一星期。”男人又把青蛙拿出来,对着它微微一笑,把它放回口袋。
“如果你亲我一下,我会变成一个美丽的公主,然后我愿意成为你的爱人一年,而且你可以对我做任何事。”再一次,男人把青蛙拿出来,对着它微微一笑,又把它放回口袋。
最后,青蛙无力地问:“我开出了这么好的条件,为什么你还不肯吻我?”男人说:“我是一个程序员,我可没时间和什么公主鬼混。不过,拥有一个会说话的青蛙,倒是蛮酷的。”