国产成人精品亚洲777人妖,欧美日韩精品一区视频,最新亚洲国产,国产乱码精品一区二区亚洲

您的位置:首頁技術(shù)文章
文章詳情頁

javascript - setTimeout第一個參數(shù)是立即執(zhí)行函數(shù),看不懂了

瀏覽:93日期:2023-03-05 13:39:59

問題描述

setTimeout第一個參數(shù)是立即執(zhí)行函數(shù),看不懂了

for (var i = 0; i < 5; i++) { setTimeout((function(i) { console.log(i); })(i), i * 1000);}

雖然結(jié)果是立即輸出0,1,2,3,4,但是不知道為啥

問題解答

回答1:

這樣其實是一下子全部打印出來的。。。不是每隔一秒打印出來。。建議這樣寫。。

for (var i = 0; i < 5; i++) { setTimeout((function(i) { return function() {console.log(i); } })(i), i * 1000);}

我來解釋一下這個為什么可以獲取到0、1、2、3、4.網(wǎng)上關(guān)于JS預(yù)解釋的文章也不少,在進入執(zhí)行上下文階段的時候函數(shù)并不會執(zhí)行,簡單來說就是當(dāng)你聲明這個函數(shù)的時候,只要不調(diào)用就不會執(zhí)行,上下文里面只會保存著這個函數(shù)的引用,可以看做這個函數(shù)保存在內(nèi)存中,只有到調(diào)用的時候函數(shù)才會執(zhí)行,我說說自己的理解,有不對的地方請指出來。如果沒有立即執(zhí)行函數(shù): 你在for循環(huán)里面實際上相當(dāng)于定義了5個定時器,但是js是單線程,這五個函數(shù)會被放到隊列里面等待執(zhí)行,舉個不一定恰當(dāng)?shù)睦樱憔桶堰@五個函數(shù)function() {console.log(i);}當(dāng)成字符串保存到內(nèi)存中,一直沒什么動靜,等到這五個函數(shù)調(diào)用執(zhí)行的時候(就是setTimeout的第二個參數(shù)的時間到了的時候),才會開始執(zhí)行這個函數(shù),因為函數(shù)里面有個i,這個時候會通過作用域鏈來查找這個i,最后在外面的作用域里面查找到了i,但是這個時候for循環(huán)已經(jīng)執(zhí)行結(jié)束了,i已經(jīng)變成4了,所以會打印出5個4.如果有立即執(zhí)行函數(shù)(比如我上面寫的那個): 你在for循環(huán)里面實際上相當(dāng)于定義了5個定時器,但是js是單線程,這五個函數(shù)會被放到隊列里面等待執(zhí)行。

(function(i) {

return function() { console.log(i);}

})(i)

但是由于外面是立即執(zhí)行函數(shù),所以會立即就執(zhí)行了,并且把i傳了進去,等到這五個函數(shù)執(zhí)行的時候,向上查找i,正好在這個立即調(diào)用函數(shù)的作用域里面查找到了i,所以會打印出0、1、2、3、4.

回答2:

你先看括住整個function的那個括號也就是:

(function (i) { console.log(i);})

這一段,理解就是把自己包成一個包裹,是一個整體,這個整體是一個函數(shù)

那么接下來怎么調(diào)用函數(shù)呢?是不是函數(shù)名()這樣,在函數(shù)名后面加上括號,并且可以傳遞參數(shù)進去

所以很自然的,就出現(xiàn)了這樣:

(function (i) { console.log(i);})(i)

這種調(diào)用,就是寫個函數(shù),用()包起來,在后面接個(),里面寫參數(shù),就直接執(zhí)行了

回答3:

就像樓上說的是立刻打印出來了,你的setTimeout根本就沒起作用。原因就是立即執(zhí)行函數(shù)執(zhí)行后沒有返回值,所以相當(dāng)于setTimeout(undefined, i*1000)。

回答4:

setTimeout要求第1個參數(shù)是一個函數(shù),這樣等第2個參數(shù)規(guī)定的時間到了之后,開始執(zhí)行第1個參數(shù)定義的函數(shù)。

當(dāng)你這么寫的時候:

for (var i = 0; i < 5; i++) { setTimeout(function(i) { console.log(i); }, i * 1000);}

你會注意到定時器已經(jīng)起作用了,只不過是每隔1秒種打出來一個undefined。因為當(dāng)執(zhí)行這個函數(shù)的時候,i已經(jīng)從循環(huán)中跳出,已經(jīng)沒有值了。

所以你改成這樣:

for (var i = 0; i < 5; i++) { setTimeout((function(i) { console.log(i); })(i), i * 1000);}

但在這種情況下,第1個參數(shù)不是一個函數(shù),而是一個表達式,也就是說會立即執(zhí)行的函數(shù),它不會等到計時器起作用才執(zhí)行,而是只要一碰到就會執(zhí)行,所以表現(xiàn)形式就是直接打出了0,1,2,3,4。

按照樓上的說法改成這樣:

for (var i = 0; i < 5; i++) { setTimeout((function(i) { return function() {console.log(i); } })(i), i * 1000);}

雖然第1個參數(shù)是一個表達式,還是會立即執(zhí)行,但是這個表達式執(zhí)行的結(jié)果不是輸出數(shù)值,而是返回一個函數(shù),這就滿足了setTimeout對第1個參數(shù)是函數(shù)的要求,并且給定了正確的輸入?yún)?shù),所以每隔1秒種會輸出一個正確的結(jié)果。

不過,為了團隊協(xié)作起見,我一般不建議這么寫,我建議還是規(guī)規(guī)矩矩按照setTimeout的標(biāo)準(zhǔn)寫法寫成這樣:

var j = 0;for (i = 0; i < 5; i++) { setTimeout(function() { console.log(j); j++; }, i * 1000);}

這樣至少對于組內(nèi)其他成員讀起來更容易理解一些。

回答5:

因為是立即執(zhí)行的函數(shù)啊,當(dāng)然立即輸出了

回答6:

函數(shù)作用域問題,改變this指向就可以了。

for (var i = 0; i < 5; i++) { setTimeout((function(i) {console.log(i); }).bind(this,i), i * 1000);}回答7:

沒有立即執(zhí)行函數(shù)的話,打印出來的是5個5,而且是每隔一秒打印,因為這里setTimeout里面的函數(shù)要等循環(huán)完成之后才會執(zhí)行,這時全局變量i就是5了。使用立即執(zhí)行函數(shù),會獲取循環(huán)中的每一個i,這里有閉包的效果,這個i這時就是一個局部變量了,存在于此函數(shù)中,每次執(zhí)行時變量i的值都不一樣。

回答8:

(function(i) { console.log(i);})(i)

聲明了馬上執(zhí)行 這樣 就是 0 1 2 3 4

然而這個沒有返回值 因此默認(rèn)是 undefined

因此你的代碼可以認(rèn)為是這樣:

for (var i = 0; i < 5; i++) { var temp = (function(i) { console.log(i); })(i); // temp 是 undefined setTimeout(temp, i * 1000);}

javascript - setTimeout第一個參數(shù)是立即執(zhí)行函數(shù),看不懂了

回答9:

理解一下原理,閉包,堆棧,事件隊列,同步,異步

翻轉(zhuǎn)一下思路:把傳進去的參數(shù)i去掉,看看是不是能正常打印,不能的話,分析一下為什么

能不能換幾種寫法,實現(xiàn)上面一樣的效果,分析一下為什么完成上面的幾點,你就知道原因 過程 結(jié)果

標(biāo)簽: JavaScript
主站蜘蛛池模板: 辽宁省| 三门峡市| 临猗县| 万州区| 茶陵县| 福安市| 石景山区| 兰州市| 杭州市| 镇原县| 蓬莱市| 大厂| 陈巴尔虎旗| 新田县| 木兰县| 贵港市| 康定县| 丰县| 廊坊市| 分宜县| 密山市| 通道| 阳春市| 桃园市| 铅山县| 都安| 佛山市| 凉山| 邢台县| 安义县| 石楼县| 梅河口市| 乌鲁木齐县| 广丰县| 镇远县| 东莞市| 洛扎县| 岳池县| 吉林市| 济源市| 华坪县|