距离上次写完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变得更简单?我不知道,拭目以待吧。

另外,下一篇博客准备搞点有点技术含量的,现在要去看球咯~