标签:
闭包是什么?
综合各种资料之后,我对闭包的理解是:
下面是一个关于闭包的例子:
通常,函数中的局部变量仅在函数的执行期间可用。一旦foo()
执行过后,我们会很合理的认为 name 变量将不再可用。
但实际并不是这样的。在上面的例子中,myName函数变成了一个闭包。
闭包是一种特殊的对象。它由两部分构成:函数,以及创建该函数的环境。环境由闭包创建时在作用域中的任何局部变量组成。因此,myName由ShowName 函数和闭包创建时作用域中存在的变量name组成。
下面是一个摘自MDN上一个关于闭包的例子。
这里应该要注意的是,add5
和 add10
都是闭包。它们共享相同的函数定义,但是保存了不同的环境。在 add5
的环境中,x
为 5。而在 add10
中,x
则为 10。
也就是说,每调用一次makeAdder(),都会创建一个新的环境,所以add5和add10并没有共享同一个环境,因此它们是独立的,互不影响。
闭包有什么用?
在这个例子里,observer是一个闭包,也是一个对象。这个对象中的属性是访问observerList这个私有变量的接口。外部无法直接访问或操作observerList,只有通过提供的接口才能实现对observerList的访问和操作。
循环中创建闭包
请看下面一个例子:
这个函数会返回一个函数数组。表面上看,似乎每个函数都会打印自己的索引值。但实际上每个函数都打印10。因为每个函数引用的都是同一个变量i.当foo()函数返回后,i的值变为10,所以每个函数执行时结果都为10.
通过创建另一个匿名函数,可以让闭包的行为符合预期。
性能问题
函数执行后,若函数中的变量被外部函数所引用(即产生闭包),则该变量并不会被JS的垃圾回收机制所回收,而是保存在内存中。
引用自MDN中的资料:
如果不是因为某些特殊任务而需要闭包,在没有必要的情况下,在其它函数中创建函数是不明智的,因为闭包对脚本性能具有负面影响,包括处理速度和内存消耗。
例如,在创建新的对象或者类时,方法通常应该关联于对象的原型,而不是定义到对象的构造器中。原因是这将导致每次构造器被调用,方法都会被重新赋值一次(也就是说,为每一个对象的创建)。
标签:
原文地址:http://www.cnblogs.com/seven-zh/p/4571020.html