闭包是什么
一个函数,返回的是一个函数,而且返回的函数中还引用了外层函数的局部变量,类似如下:
function outer(x){
return function inner(){
x+=1;
return x;
};
}
当我们outer(3)时,返回inner函数的首地址,要得到真正的返回值x,需要outer(3)();
闭包中内层函数的延迟调用
闭包中的内层函数是会延迟调用的,比如
function f() {
var list = [];
for (var i=1; i<=3; i++) {
list.push(function () {
return i * i;
});
}
return list;
}
像上面的代码,先看外层函数,返回一个数组list,list=[i*i , i*i , i*i],按照常理,list应该是[1,4,9],实际呢,[16,16,16]。也就是说list=[function , function , function],内层的匿名函数还没执行,知道我们要x = f(),console.log(x[0])才会真正的调用
注意:我们不应该在返回函数中引用循环变量以及后续会变化的量
如果想要内层函数立即执行
function f() {
var list = [];
for (var i=1; i<=3; i++) {
list.push(
(function (n) {
return function () {
return n * n;
}
})(i)
);
}
return list;
}
我们可以看到list好像还是push了一个function进去,是这样吗,其实push进list的是
(function(n) {return function() {return n*n;}}) (i),没错,仔细看,本来function(n){...}()就已经算是调用这个函数了,但是在JavaScript中还得在外层加一个()才表示立即执行这个匿名函数,把参数i传进去,因为是function(n),i把形参n替换了,list中的元素就是function(n)的执行结果了
简单实例
计数器:
var counter = function creat(begin){
var x = begin;
return function(){
x += 1;
return x;
};
}
//测试
counter(0)();
counter(0)();
counter(0)();
function make_pow(n) {
return function (x) {
return Math.pow(x, n);
}
}
//测试
pow3 = make_pow(3);
pow3(4);//4**3