距离上次写完prototype的笔记,已经3年了……时间过得真快,我也真是能拖……公司开会有同事问起闭包到底是个什么东西,这才决定,这次一定要写了。
一、什么是函数对象
其实,对于只熟悉Java的程序员来说,理解闭包的一个障碍就是,不知道函数也可以是个对象。在我们的概念里,对象就是类的实例,函数就是对象的方法。代码中的每一个变量,都是用来存放数据的。然而事实上,这是Java语言的一个简化,就好像Java的垃圾收集器一样。这个世界上的很多很多语言,特别是支持闭包的语言,函数都是作为第一级对象而存在的。请看以下JavaScript代码:
var func1 = function(){return 0;}
以上这段代码在Java中是不可想象的,我们声明了一个变量func1,这个变量是一个函数。既然它一个函数,那么他可以执行;
var i = func1(); //这是可以的
同样,既然它是一个变量,那么它也可以做变量能做的事。
var func2 = func1;
var j = func2(); //func2这个变量现在跟func1都表示同一个函数。
上面的代码展示了函数对象可以像普通对象一样进行赋值操作,那么,它当然也可以作为另一个函数的返回值咯。我们再看代码:
funcion getFunc(){
var func1 = function(){return 0;}
return func1;
}
var func2 = getFunc();
var j = func2();
我们通过getFunc这个函数,返回一个func1这个函数,并赋值给func2,因为函数也是对象嘛,这当然是可以的。
二、JavaScript里的闭包
好,接下来,我们做一点小小的改动,闭包就出现了!
funcion getFunc(){
var x = 0;
var func1 = function(){return x;}
return func1;
}
var func2 = getFunc();
var j = func2();
注意,我在写func1的时候,并不是直接返回0,而是返回一个变量x,而这个x,并不是定义在func1的函数里面,而是定义在getFunc的函数里面,它return出去的x,不是自己的x,是别人的x(好坏啊,这不是借花献佛吗)。这意味着,function(){return x;},这一句代码并不能完整的表达这个函数,还要加上var x = 0;这一句。x这个变量,虽然没有写在函数体内,但是他们一起组成了一个不能分割的整体,这个整体,就叫做闭包!下面来看wikipedia上关于闭包的定义。
在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。
结合定义来看,这里的x就是那个被引用的自由变量,它和函数func1一起存在,他们是作为一个整体被返回出去,赋值给了func2。即使到了最后一句话var j = func2(); 这里j的值就会等于x的值,也就是0。
三、一点废话
闭包这个词最近较火,好像是因为Java7准备引入闭包引发了广泛的讨论。虽然闭包是个好东西,但是Java真的需要它吗,难道现在有些客户需求因为没有闭包而实现不了吗?难道真有的把函数提为第一级对象会使Java变得更简单?我不知道,拭目以待吧。
另外,下一篇博客准备搞点有点技术含量的,现在要去看球咯~