##闭包
###什么是闭包 这几天在一直在研究js的闭包,算是对它有自己的一点点理解,首先维基百科是这样说的
在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。
Peter J. Landin 在1964年将术语闭包定义为一种包含环境成分和控制成分的实体。
有点复杂,我们用最简单的代码来说一下
function x() {
var tmp = 1;
function a(){
console.log(tmp++);
}
a();
}
x();
x();
x();
我们定义了一个函数x,里面有一个变量tmp,又有一个内部函数a(),并且最后执行了这个a(),我们执行这个x三次。发现都打印出来都是1,这种用法虽然很奇怪,但是结果我们是可以理解的,很简单,但是如果我们把a返回,在外部执行呢
function x() {
var tmp = 1;
function a(){
console.log(tmp++);
}
return a;
}
var b = x();
b(); //1
b(); //2
b(); //3
首先我们定义了一个函数,里面有一个变量,一个函数(直接返回了),这个x我们称为外部函数,里面返回的我们成为内部函数,tmp我们称为外部函数的变量,外部变量,然后我们调用x,返回的函数,我们赋值给b,接下来,我们调用b,三次,第一次,结果为1,第二次第三次结果是2和3。 是不是觉得有点神奇,这个tmp是我们在内部定义的,正常来说,我们调用了x以后,我们就无法访问到tmp的了,但是我们现在发现这个tmp并没有被销毁,而且我们外部可以访问对并且对其进行了操作,其实这个 b就是一个闭包
那么,要怎么形成这个闭包呢
- 在一个函数的内部定义了一个函数(x里面定义了a)
- 这个函数引用了一个外部的变量(在内部函数a里面引用了外部函数的tmp)
- 并且把这个函数返回了
只有满足了这三个条件,就是一个闭包
###闭包对于外部的值的使用是引用 闭包在实际调用的时候,才去找到该值的实际值,而不是在定义的时候的值,这个要怎么理解呢,还是上代码
function createFunctions() {
var result = new Array();
for (var i = 0; i < 10; i++) {
result[i] = function() {
return i;
};
}
return result;
}
var a = createFunctions();
var test1 = a[0]();
var test2 = a[1]();
console.log(test1); //10
console.log(test2); //10
这里我们定义了一个函数createFunctions,在里面循环10次,创建了10个函数,赋给了result,最后把result返回。我们调用这个函数,吧返回值给a,这个时候a就是一个拥有10个函数的一个数组,我们调用其中两个,发现打印出来的结果都是10,为什么呢,如果i都是10,那么在循环的时候是怎么可以循环成功的,这就是我上面说的,闭包里面的内部函数,对于外部值的使用,都是引用,也就是result[i]这里的i是在定义的时候已经确定了值,0-9,而内部的i只是一个引用,需要我们在实际调用的时候a[0]和a[1]的时候,再去找这个i的值,这个时候i因为是闭包里面的变量,在循环完以后并没有销毁,还保存在了闭包里面,值为10。
那么利用闭包的特效,我们可以做什么事情呢,首先,因为它一直在内存中的特性,我们可以用它来做计算器。
function count(num) {
return function() {
return num++;
}
}
a = count(0);
console.log(a()); //0
console.log(a()); //1
console.log(a()); //2
console.log(a()); //3
这是比较简单的应用,还有一些比较高级点的,可以看看我的 github