摘要:所以根據(jù)不同的,在時(shí)間軸上定義匿名函數(shù)。當(dāng)然,由于匿名函數(shù)指向的是全局變量,此時(shí)主執(zhí)行結(jié)束早已為,所以彈出。
A
for (var i=5; i>=1; i--) { setTimeout( function timer() { document.write(i+"
"); }, i*3000 ); } // 0 0 0 0 0 // 保存執(zhí)行后,3秒后彈出第一個(gè)console(0),之后隔3秒彈出第二個(gè),依次按照時(shí)間執(zhí)行。
B
for (var i=5; i>=1; i--) { setTimeout( function timer() { document.write(i+"
"); }, 3000 ); } // 0 0 0 0 0 // 保存執(zhí)行后,3秒后所有的console一齊彈出
C
for (var i=5; i>0; i--) { !function (i) { setTimeout( function timer() { console.log(i); }, i*3000 ); }(i) } // 1 2 3 4 5 每隔3秒依次彈出這里我抽象一下setTimeout的隊(duì)列執(zhí)行結(jié)構(gòu): 注意,時(shí)間設(shè)定與閉包沒(méi)有關(guān)系!
當(dāng)所有的非隊(duì)列結(jié)構(gòu)代碼都執(zhí)行完畢,函數(shù)調(diào)用棧清空后,這些setTimeout才會(huì)進(jìn)入隊(duì)列數(shù)據(jù)棧等待執(zhí)行
。而時(shí)間,就是按照?qǐng)D中那樣:
A與B的區(qū)別就是時(shí)間i*3000與3000的區(qū)別。
setTimeout的定義是與正常的JS執(zhí)行是同步的,而函數(shù)的執(zhí)行是異步的,所以,根據(jù)不同的i值,setTiemout在時(shí)間軸上已經(jīng)定義了函數(shù)。
而且可以發(fā)現(xiàn),時(shí)間設(shè)置里的i是根據(jù)for循環(huán)變化的(5 4 3 2 1),這也反證了setTimeout的定義時(shí)是與主JS程序同步。所以根據(jù)不同的i*3000,在時(shí)間軸上定義匿名函數(shù)。執(zhí)行時(shí),每隔3秒,彈出一個(gè)0。
當(dāng)然,由于匿名函數(shù)指向的是全局變量i,此時(shí)主JS執(zhí)行結(jié)束早已為0,所以彈出0。
在B代碼中,沒(méi)有設(shè)置i與時(shí)間的計(jì)算,所以循環(huán)中產(chǎn)生的5個(gè)匿名函數(shù)都是定義在3秒這個(gè)時(shí)間節(jié)點(diǎn)上,當(dāng)主JS代碼執(zhí)行完畢,開(kāi)始執(zhí)行隊(duì)列結(jié)構(gòu)棧中的函數(shù)時(shí),5個(gè)函數(shù)在3秒后同時(shí)執(zhí)行,所以會(huì)彈出5個(gè)0。而對(duì)于匿名函數(shù)中的i取值,這里自然是來(lái)自全局變量中的i,主JS程序執(zhí)行完畢i自然運(yùn)算完畢值為0,所以5個(gè)i都是0;
C:引入閉包的情況和B其實(shí)是類似的,時(shí)間設(shè)定與匿名函數(shù)執(zhí)行始終井水不犯河水,所以時(shí)間軸與B相同,不同的是匿名函數(shù)里的i值。
圖中嵌套的正方形就抽象為自調(diào)用函數(shù),每一次的循環(huán)中產(chǎn)生的i值,會(huì)傳入自調(diào)用函數(shù),保存在其變量對(duì)象中。由于匿名函數(shù)里的是自調(diào)用函數(shù)的閉包,匿名函數(shù)引用了變量對(duì)象里的i,所以每個(gè)自調(diào)用函數(shù)的變量對(duì)象不會(huì)在執(zhí)行完畢后被回收,得以保持繼續(xù)被匿名函數(shù)引用著。最后實(shí)現(xiàn)最終效果。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/87066.html
摘要:要是當(dāng)前代碼耗時(shí)很長(zhǎng),有可能要等很久,所以并沒(méi)有辦法保證,回調(diào)函數(shù)一定會(huì)在指定的時(shí)間執(zhí)行。需要監(jiān)聽(tīng)文字改變,每一次改變都會(huì)調(diào)用一次回調(diào)函數(shù),現(xiàn)在需要的一種實(shí)現(xiàn)是在用戶停止鍵盤事件一段時(shí)間后,去發(fā)送一個(gè)請(qǐng)求。 1、開(kāi)胃菜,setTimeout為何物 首先看一下w3school上面對(duì)于setTimeout的解釋 setTimeout(fn,millisec) 方法用于在指定的毫秒數(shù)后調(diào)用函...
摘要:引擎單線程機(jī)制首先明確,引擎是單線程機(jī)制。是單線程執(zhí)行的,無(wú)法同時(shí)執(zhí)行多段代碼。解析是單線程的,所以會(huì)先執(zhí)行再,但這個(gè)循環(huán)體是死循環(huán),所以永遠(yuǎn)不會(huì)執(zhí)行。 Javascript 引擎單線程機(jī)制 首先明確,JavaScript引擎是單線程機(jī)制。 JavaScript 是單線程執(zhí)行的,無(wú)法同時(shí)執(zhí)行多段代碼。當(dāng)某一段代碼正在執(zhí)行的時(shí)候,所有后續(xù)的任務(wù)都必須等待,形成一個(gè)任務(wù)隊(duì)列。一旦當(dāng)前任務(wù)...
摘要:開(kāi)始執(zhí)行文件,同步代碼執(zhí)行完畢后,進(jìn)入事件循環(huán)。時(shí)間未到的時(shí)候,如果有事件返回,就執(zhí)行該事件注冊(cè)的回調(diào)函數(shù)。對(duì)于多次執(zhí)行輸出結(jié)果不同,需要了解事件循環(huán)的基礎(chǔ)問(wèn)題。 1. 說(shuō)明 nodejs是單線程執(zhí)行的,同時(shí)它又是基于事件驅(qū)動(dòng)的非阻塞IO編程模型。這就使得我們不用等待異步操作結(jié)果返回,就可以繼續(xù)往下執(zhí)行代碼。當(dāng)異步事件觸發(fā)之后,就會(huì)通知主線程,主線程執(zhí)行相應(yīng)事件的回調(diào)。 本篇文章講解n...
摘要:如果對(duì)語(yǔ)法分析和預(yù)編譯,還有疑問(wèn)引擎執(zhí)行的過(guò)程的理解語(yǔ)法分析和預(yù)編譯階段。參與執(zhí)行過(guò)程的線程分別是引擎線程也稱為內(nèi)核,負(fù)責(zé)解析執(zhí)行腳本程序的主線程例如引擎。以上便是引擎執(zhí)行宏任務(wù)的整個(gè)過(guò)程。 一、概述 js引擎執(zhí)行過(guò)程主要分為三個(gè)階段,分別是語(yǔ)法分析,預(yù)編譯和執(zhí)行階段,上篇文章我們介紹了語(yǔ)法分析和預(yù)編譯階段,那么我們先做個(gè)簡(jiǎn)單概括,如下: 1、語(yǔ)法分析: 分別對(duì)加載完成的代碼塊進(jìn)行語(yǔ)法...
摘要:如果對(duì)語(yǔ)法分析和預(yù)編譯,還有疑問(wèn)引擎執(zhí)行的過(guò)程的理解語(yǔ)法分析和預(yù)編譯階段。參與執(zhí)行過(guò)程的線程分別是引擎線程也稱為內(nèi)核,負(fù)責(zé)解析執(zhí)行腳本程序的主線程例如引擎。以上便是引擎執(zhí)行宏任務(wù)的整個(gè)過(guò)程。一、概述 js引擎執(zhí)行過(guò)程主要分為三個(gè)階段,分別是語(yǔ)法分析,預(yù)編譯和執(zhí)行階段,上篇文章我們介紹了語(yǔ)法分析和預(yù)編譯階段,那么我們先做個(gè)簡(jiǎn)單概括,如下: 1、語(yǔ)法分析: 分別對(duì)加載完成的代碼塊進(jìn)行語(yǔ)法檢驗(yàn),語(yǔ)...
閱讀 2894·2021-11-24 09:38
閱讀 3518·2021-11-23 09:51
閱讀 987·2021-09-09 11:52
閱讀 4039·2021-08-11 11:18
閱讀 1115·2019-08-30 14:05
閱讀 3235·2019-08-30 11:23
閱讀 1773·2019-08-29 17:02
閱讀 1132·2019-08-26 13:49