闭包是javascript中绕不开的话题,关于闭包的一些概念和应用,这方面资料比较多,在此就不再赘述。众所周知,闭包的一个作用就是 让一些变量始终保持在内存中 ,在此我用一些实际代码对这句话作进一步的理解。
demo1:
function closure(){
var n = 0;
function test() {
console.log(++n);
}
test()
test()
}
closure(); //输出1,2(这个很好理解,不多说)
demo2:
function test(){
var i=0;
return function(){
console.log(i++);
}
}
var fn = test();
fn(); //输出0
fn(); //输出1
上述代码中,fn就是执行函数test()返回的匿名函数。由于fn又是一个全局变量,生命周期一直存在,且这个匿名函数引用了父函数test里面的一个局部变量,所以变量i的状态会被一直保存.
demo3:
function test(){
var i=0;
return function(){
console.log(i++);
}
}
test()(); //输出0
test()(); //输出0
上述代码中,执行test()返回的是其内部的匿名函数,但是执行完test()()以后,该匿名函数的生命周期已经结束,所以变量i的状态没有得到保存。
最近在简书上读到一篇有趣的文章,其中一些代码如下:
for (var i = 0; i < 5; i++) {
setTimeout((function(i) {
console.log(i);
})(i), i * 1000);
} //输出0,1,2,3,4
上述代码中有一个setTimeout()函数,其使用格式为setTimeout(func,time),意思是至少过time时间后,执行func。有了这样的认识后,我们可以把func等价成:
(function(i){console.log(i)})(i)这个自执行函数。所以这个事情分两步,首先每次循环自执行函数肯定会立即执行一次,会依次输出1,2,3,4。其次,每过time时间,执行一次func,但是在上述代码中,func等价于一个立即执行函数,没有返回值,故什么也不会做。
如果把上述代码改成这样:
for (var i = 0; i < 5; i++) {
var j=7;
setTimeout((function(i) {
console.log(i);
return function(){
console.info(j++);
}
})(i), i * 1000);
}
上述代码会依次输出0,1,2,3,4, 7,8,9,10,11(结合这个例子理解上一个问题,就容易多了)
如果把上面的代码改成这样呢?
for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i);
}, i * 1000);
}
运行上面的代码会输出5个5(这一点现在可以理解了吧),有人不解的是为什么是每隔一秒输出5而不是隔五秒输出5。setTimeout(func,time)这个函数延迟执行的只是func里面的动作,而time的值是不存在延迟的。上面执行for循环,相当于:setTimeout(func,1000),setTimeout(func,2000) .... 第一次setTimeout执行的时候等了一秒(准确地说,至少要等一秒),第二次setTimeout执行的时候等2秒,但是前面第一次执行的setTimeout函数时,已经等了一秒,所以只需再等一秒就可以立即执行了。在这里,需要弄明白的是,setTimeout函数延迟执行的时间,起点是从time开始赋值的时候计算的,不是从上一个setTimeout函数执行完开始算的。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。