Javascript 闭包理解
文艺版
If you can't explain it to a six-year-old, you really don't understand it yourself.
//从前:
//有一位公主......
function princess() {
//她生活在一个充满奇幻冒险的世界里, 她遇到了她的白马王子, 带着他骑着独角兽开始周游这个世界,与巨龙战斗,巧遇会说话的动物,还有其他一些新奇的事物。
var adventures = [];
function princeCharming() { /* ... */ } //白马王子
var unicorn = { /* ... */ }, //独角兽
dragons = [ /* ... */ ], //龙
squirrel = "Hello!"; //松鼠
adventures.push(unicorn, dragons, squirrel, ....);
//但是她不得不回到她的王国里,面对那些年老的大臣。
return {
//她会经常给那些大臣们分享她作为公主最近在外面充满奇幻的冒险经历。
story: function() {
return adventures[adventures.length - 1];
}
};
}
//但是在大臣们的眼里,总是认为她只是个小女孩......
var littleGirl = princess();
//....讲的是一些不切实际,充满想象的故事
littleGirl.story();
//即便所有大臣们知道他们眼前的小女孩是真的公主,但是他们却不会相信有巨龙或独角兽,因为他们自己从来没有见到过。大臣们只会觉得它们只存在于小女孩的想象之中。
//但是我们却知道小女孩述说的是事实.......
概念版
什么是闭包?
闭包(Closure)这个词的意思是封闭,将外部作用域中的局部变量封闭起来的函数对象称为闭包。被封闭起来的变量与封闭它的函数对象有相同的生命周期。
什么是函数对象?
函数对象是作为对象来使用的函数,这里的对象是指编程语言操作的数据。
函数对象与闭包
函数对象不一定是闭包。
C 语言中,可以获取一个函数的指针,并通过指针间接调用此函数。这就是 C 语言中的对象(函数对象也是对象)。但 C 语言中的函数对象不是闭包——它不能访问外部作用域的局部变量。
Javascript 中,每个函数都有一个与之相关联的作用域链。每次调用 JavaScript 函数的时候,都会为之创建一个新的对象用来保存局部变量,并把这个对象添加至作用域链中。当函数返回时,再将这个对象删除,此对象会被当做垃圾回收。但如果这个函数定义了嵌套的函数,并将它存储在某处的属性里,就意味着有了一个外部引用指向这个嵌套的函数。它就不会被当作垃圾回收,它所指向的变量绑定对象同样不会被回收。
由此可见,JavaScript 中的函数对象是闭包——可以把外部作用域的局部变量“封闭”起来。
什么是对象?
面向对象中的“对象”是指问题空间中的元素(猫、狗)及其在解空间中的表示(new Cat(); new Dog())。对象是过程(函数)与数据的结合。
对象与闭包
对象是在数据中以方法的形式内含了过程,闭包是在过程中以环境的形式内含了数据。所谓“闭包是穷人的对象”、“对象是穷人的闭包”,就是说使用其中的一种方式,就能实现另一种方式能够实现的功能。
应用场景
保护函数内的变量安全:如迭代器、生成器。
在内存中维持变量:如果缓存数据、柯里化。
个人理解
在javascript中,闭包就是一个函数返回一个 函数内部函数 的现象,就像是这样
function hFive(){
var name="h-five.com";
var year=123;
function reOut(){
console.log(name+" "+year);
}
return reOut;
}
var test=hFive();
test();//h-five.com 123
这就是一个简单的闭包,test可以调用函数hFive内部的变量使用,但是test所在上下文却不能调调用hFive函数内部的变量,这样保护函数内的变量安全,起到私有变量的作用,但是这些私有变量会占用内存空间,富哦多饿使用,又不释放内存,会降低程序性能。
参考资源
http://www.zhihu.com/question/19554716/answer/40356052
http://www.zhihu.com/question/19554716/answer/23064179