[js] 大家聊聊 “闭包--Closure” 这个前端面试必问的永恒话题

2013-05-30 15:58:55 +08:00
 emohacker
这个永恒的话题一般是这样的:

你是如何理解闭包的?什么情况下用闭包?

我把闭包简单理解为,是函数返回后并没有释放内存中的资源。

个人使用情况:
1、封装,对象有私有属性或方法不希望外部直接访问的时候。
2、缓存。
3、类似独立的命名空间,避免变量污染到全局的情况,比如jQuery中
(function( window , undefined ){

})( window );

另一考题,以下这两种写法的效果是一样的,为什么?

var abc = (function(){
return{.......};
})();

var abc = (function(){
return{.......};
}());
7796 次点击
所在节点    JavaScript
30 条回复
typing
2013-05-30 16:11:34 +08:00
对于Closure, 我现在印象最深的例子是这个:
(对比注释行的区别)

var callbacks = [];

for(var i = 0; i < 3; ++i){
// callbacks.push(function() {console.log(i);});

callbacks.push(function(i){return function(){console.log(i);};}(i));
}

_.each(callbacks, function(f) {f();});
Golevka
2013-05-30 17:04:28 +08:00
没有释放内存中的资源什么的... 提到closure就不得不提到lexical scoping. 从实现角度来说确实是function definition和其所在的environment的绑定.
xatest
2013-05-30 17:19:42 +08:00
为什么回复这个话题的都是ACG头像?。。。我来打破队形,对比一下函数和闭包:
函数 = {抽象}
闭包 = {抽象 + upvalue + env}
otakustay
2013-05-30 17:19:51 +08:00
我有一个专门说闭包的PPT,能把这个消化掉,我觉得闭包已经没有啥能难到你了
https://skydrive.live.com/redir.aspx?resid=5AF9669191A78C07!197


另外关于闭存回收的问题,我也有一个专门的博客总结过
http://otakustay.com/about-closure-and-gc/
yimity
2013-05-30 17:19:59 +08:00
我觉得要理解闭包首先要理解词法作用域,也就是函数执行时候查找变量等的过程,从函数最里面找,一直找到最外面的函数,如果内层函数没有定义的变量在外层找到,那么就可以说这个是闭包了。也由此可见,javascript 只要是函数,都可以形成闭包。

私有变量,函数等
防止全局变量污染
然后就是保存某些变量的值,防止取得值是最终结果。
初始化等。类似于常量。

效果是一样的,先强制表达式,然后调用。
otakustay
2013-05-30 17:22:54 +08:00
@xatest 可见玩前端的都是些什么宅……
emohacker
2013-05-30 17:24:43 +08:00
@typing 亲,你想通过这个例子说明一个什么问题?
emohacker
2013-05-30 17:25:33 +08:00
@Golevka 虽然木有看懂,但是感觉很厉害的样子~
otakustay
2013-05-30 17:31:30 +08:00
@emohacker @typing 的那个是典型装饰lift问题,很坑的一个事,运行过你会明白的,而且确实是闭包特性导致
switch
2013-05-30 17:35:34 +08:00
(function( window , undefined ){

})( window );
這個不算是閉包,只是一個匿名函數自調用而已。
emohacker
2013-05-30 17:36:21 +08:00
@otakustay 学习
emohacker
2013-05-30 17:47:25 +08:00
@switch 我也挺纳闷的,之前在网上看有些人说是,看上去也有点像,就记下了,面试时是这么回答的,但是用闭包的概念去套,貌似是解释不通的。
学艺不精,未得其精髓,深入学习中~
Golevka
2013-05-30 17:48:06 +08:00
@otakustay 不玩前端的路过, 并表示目前的工作比较偏硬件...
@emohacker 关于lexical scoping和closure的关系5L的解释就很易懂了. SICP ch3对此也有涉及, 并且也是用的带upward的模型.
emohacker
2013-05-30 17:48:12 +08:00
@xatest 各种宅,哈哈哈
xatest
2013-05-30 17:51:09 +08:00
我也不玩前端的,平时用到闭包最多的是写lua,给篇专门讲闭包的文章,举了各种语言(包括js)的例子:
https://www.ibm.com/developerworks/cn/linux/l-cn-closure/
emohacker
2013-05-30 17:52:12 +08:00
@switch 可是通过 @yimity 5楼的回答,纠其根源。。。那个匿名函数的立即执行貌似又算是闭包。。。我还是有点不清晰
renyuan1985
2013-05-30 17:52:22 +08:00
@switch 恩是的,我也这样理解的,不知道我理解的闭包对不对http://renyuanz.com/javascript-closure.html
heroicYang
2013-05-30 21:24:35 +08:00
直白点一句话剧透:闭包就是内部函数能访问外部的变量。如果要深究,5楼已答,但是个人觉得这个概念你越是深究反而越糊涂。
Hongmin
2013-05-30 21:36:20 +08:00
突然想到一点,关于C语言函数中的static变量。

int counter() {
static unsigned v = 0;
return v++;
}
是不是一个闭包?
davepkxxx
2013-05-30 21:39:27 +08:00
关于那个考题

var abc = (func)();



var abc = (func());

的结果当然没区别……

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/70662

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX