JavaScript面向对象程序设计(7): 闭包

闭包这个概念看上去很深奥,这个词在离散数学里面的意思确实比较难于理解。在这里,咱们先能够把闭包理解成是一种匿名函数或者匿名类。
 
1. 什么是闭包?
 
什么是闭包?一种正式的解释是:所谓闭包,指的是一种拥有不少变量而且绑定了这些变量的环境的表达式(一般是一个函数),于是这些变量也是这个表达式的一部分。
 
相信不少人都不会理解这个定义,由于他的学术味道太浓了——或许你喜欢从字面的语法上进行分析:首先,它是一个表达式,这个表达式绑定了不少变量以及这些变量的环境。不过这并无什么意义,这依然不会告诉咱们什么是闭包。
 
那么,来看一个例子:
 
function add(a) {
         return function(b) {
                 return a + b;
        };
}
var func = add(10);
alert(func(20));
 
我想通过了前面有关函数的描述,这个例子应该很清楚的理解。JavaScript里面的函数就是对象,他能够作对象能作的一切事情——咱们首先定义了一个函数add,它接受一个参数,这个函数返回一个匿名函数,这个匿名函数也接受一个参数,而且会返回这个参数同外部函数的那个参数的和。所以在咱们使用的时候,咱们将add返回的匿名函数赋值给func,而后调用func,就返回了这两个数的和。
 
当咱们建立一个这样的函数,这个函数内部的一个变量可以在函数外面被引用时,咱们就称建立了一个闭包。仔细的品味一下:这就是那个闭包的定义。
 
看看咱们的代码:首先,它有一个内部变量,就是那个匿名函数;其次,这个函数将匿名函数返回了出去,以便外面的变量能够引用到内部定义的变量。
 
2. 闭包的做用
 
闭包有什么用呢?或许如今还看不出来,那么看看这段代码:
 
function inc(a) {
         var i = 0;
         return function() {
                 return i;
        };
}
var num = inc();
alert(num());
 
原本,这个变量 i 在函数外面是访问不到的,由于它是 var 定义的,一旦跳出做用域,这个变量就被垃圾回收了,可是,因为咱们使用了闭包,在外面是可以访问到这个变量的,所以它并不被垃圾回收!
 
若是仍是不明白闭包的做用,那么看一段应该很熟悉的代码:
 
function Person() {
         var id;
         this.getId = function() {
                 return id;
        }
         this.setId = function(newId) {
                id = newId;
        }
}
var p = new Person();
p.setId(1000);
alert(p.getId()); // 1000
alert(p.id); // undefined
 
咱们定义一个类Person,它有一个id属性。如今这个属性的行为很像是私有变量——只能经过 setter 和 getter 函数访问到。没错,这就是闭包的一个用途:制造类的私有变量!
 
闭包还有一个做用:在内存中维护一个变量,不让垃圾回收器回收这个变量。这里的例子就再也不举出了。
 
这里咱们只是简单的说了JavaScript的闭包的概念,并无涉及闭包的内存模型等等之类。这是一个至关重要的概念,Java社区中的部分红员一直对闭包求之不得,C#也已经在最新版本中添加了闭包的概念,只不过在那里称为lambda表达式。
相关文章
相关标签/搜索