闭包是JS的一个特色,也是一个难点。利用闭包可以实现:
1.在函数外部访问函数内部的局部变量
2.保存函数的局部变量,使之在函数返回时不被回收
3.实现私有成员和方法的封装
看起来,很多的JS应用都需要依赖闭包来实现,所以弄清楚闭包有利于我们写出更高质量的代码。
什么是闭包?
闭包,是指语法域位于某个特定的区域,具有持续参照(读写)位于该区域内自身范围之外的执行域上的非持久型变量值能力的段落。这些外部执行域的非持久型变量神奇地保留它们在闭包最初定义(或创建)时的值(深连结)
闭包的定义晦涩难懂,但说得确实是最全面的。简单来说,闭包是一个对象,从闭包里可以访问到其上一级作用域里的局部变量。由于闭包的存在,这些变量在上一级函数执行完后没有被销毁,而是被保存在了内存中。
闭包是怎么形成的?
function f2(){ var j=0; console.log("hello world"); function f3(){ console.log(j); } return f3; }
这是上次在说作用域链的时候用到的一个例子改了一下,添加了return语句。在执行f2函数时,函数f3被定义。根据作用域链的知识,函数f3可以访问到f2的活动对象。换一种说法,函数f3的作用域链应该是f2的运行期上下文的作用域链。如果没有return语句,当f2执行完毕后f2的运行期上下文会被销毁,而活动对象亦然。但当添加了return语句后,将有一个f2外部的引用指向f3,f3在f2执行完毕后仍然留在了内存里,这个时候f2的运行期上下文也被保留在了内存里,而函数f3就是一个闭包。
上次说到,with语句或try...catch语句可以在执行某段代码时临时改变作用域链,那么在with代码块或异常代码块里定义的内部函数是不是也是闭包?答案是YES!
恰当使用闭包
上面提到过,闭包很强大,许多JS应用离不开闭包。但是,绝不可滥用闭包。每利用以上方法将一个闭包赋值给一个变量时,一个运行期上下文将会被保留在内存里,频繁进行这样的操作将导致内存泄漏的问题。
关于闭包的样例和更多解释
关于闭包有很多讲得很好的解释,就不做搬运了。
http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html
http://www.cnblogs.com/rubylouvre/archive/2009/07/24/1530074.html
http://www.jb51.net/article/18303.htm
http://www.oschina.net/question/28_41112?fromerr=k4oXcGcE