javascript中閉包的一些理解
閉包是javascript中繞不開的話題,關于閉包的一些概念和應用,這方面資料比較多,在此就不再贅述。眾所周知,閉包的一個作用就是 讓一些變量始終保持在內存中 ,在此我用一些實際代碼對這句話作進一步的理解。
demo1:
function closure(){
var n = 0;
function test() {
console.log(++n);
}
test()
test()
}
a(); //輸出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 * 000);
}
運行上面的代碼會輸出5個5(這一點現在可以理解了吧),有人不解的是為什么是每隔一秒輸出5而不是隔五秒輸出5。setTimeout(func,time)這個函數延遲執行的只是func里面的動作,而time的值是不存在延遲的。上面執行for循環,相當于:setTimeout(func,1000),setTimeout(func,2000) .... 第一次setTimeout執行的時候等了一秒(準確地說,至少要等一秒),第二次setTimeout執行的時候等2秒,但是前面第一次執行的setTimeout函數時,已經等了一秒,所以只需再等一秒就可以立即執行了。在這里,需要弄明白的是,setTimeout函數延遲執行的時間,起點是從time開始賦值的時候計算的,不是從上一個setTimeout函數執行完開始算的。
來自:https://segmentfault.com/a/1190000008571702