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