


setTimeout會(huì)把回調(diào)放到代碼執(zhí)行完畢后,再做處理,so

所以就不難理解為什么第一張圖會(huì)打印5個(gè)5了,因?yàn)椴还躶etTimeout再快,也得在程序執(zhí)行完畢后打印,而程序執(zhí)行完畢時(shí),for已經(jīng)循環(huán)了5次了.....
所以呢,還有個(gè)問(wèn)題,在setTimeout把方法放到任務(wù)隊(duì)列之后,會(huì)不會(huì)保留上下文環(huán)境?答案是肯定的。
- 無(wú)論函數(shù)是在哪里調(diào)用,也無(wú)論函數(shù)是如何調(diào)用的,其確定的詞法作用域永遠(yuǎn)都是在函數(shù)被聲明的時(shí)候確定下來(lái)的。
- 當(dāng)定義一個(gè)函數(shù)時(shí),它實(shí)際上保存一個(gè)作用域鏈。
- 當(dāng)調(diào)用這個(gè)函數(shù)時(shí),它創(chuàng)建一個(gè)新的對(duì)象來(lái)儲(chǔ)存它的參數(shù)或局部變量,并將這個(gè)對(duì)象添加保存至那個(gè)作用域鏈上,同時(shí)創(chuàng)建一個(gè)新的更長(zhǎng)的表示函數(shù)調(diào)用作用域的“鏈”。
- 對(duì)于嵌套函數(shù)來(lái)說(shuō),情況又有所變化:每次調(diào)用外部函數(shù)的時(shí)候,內(nèi)部函數(shù)又會(huì)重新定義一遍。因?yàn)槊看握{(diào)用外部函數(shù)的時(shí)候,作用域鏈都是不同的。內(nèi)部函數(shù)在每次定義的時(shí)候都要微妙的差別---在每次調(diào)用外部函數(shù)時(shí),內(nèi)部函數(shù)的代碼都是相同的,而且關(guān)聯(lián)這段代碼的作用域鏈也不相同。

- 當(dāng)使用var聲明變量的時(shí)候,沒(méi)有塊級(jí)作用域,因此每次循環(huán)中聲明的setTimeout的回調(diào),是去更高一級(jí)的作用域中尋找變量i。
- 當(dāng)使用let聲明變量的時(shí)候,有獨(dú)立的塊級(jí)作用域,因此聲明setTimeout回調(diào)的時(shí)候,是在本次循環(huán)的塊級(jí)作用域{}中尋找變量i。
如上圖,在定義循環(huán)時(shí),同時(shí)定義n,在回調(diào)中修改n的值以修改回調(diào)執(zhí)行結(jié)果,如果是var聲明的,則第一次執(zhí)行的結(jié)果會(huì)對(duì)后面兩次造成影響,而使用let聲明n,則三次循環(huán)完全互不干擾,可知在使用let定義n時(shí),循環(huán)定義的三個(gè)回調(diào)函數(shù)的作用域鏈被各自分隔開(kāi)。var聲明的i和let聲明的i在作用域鏈上的位置不同。
最后總結(jié)一下:
不管是var也好,let也好,循環(huán)定義的若干個(gè)setTimeout的回調(diào)都屬于同一個(gè)上級(jí)作用域,但是回調(diào)之間是獨(dú)立存在的,不會(huì)相互影響;不一樣的是:var和let在各自作用域鏈上的位置不同,var沒(méi)有塊級(jí)作用域,所以var所在作用域?qū)儆谏霞?jí)作用域;let有塊級(jí)作用域,所以在for循環(huán)的時(shí)候,i的作用域被限制在了{(lán)}代碼塊之間,分別在三個(gè){}中定義setTimeout回調(diào)的時(shí)候,i在作用域鏈中的位置分屬三個(gè)回調(diào)所在的塊級(jí)作用域,互不干擾。


PS:只有在調(diào)用到塊級(jí)作用域中變量的時(shí)候,才會(huì)將塊級(jí)作用域添加到作用域鏈中
PS2:三個(gè)回調(diào)并非在一個(gè)塊級(jí)作用域下被依次聲明,而是將塊級(jí)作用域循環(huán)了三次,每次分別聲明了自己作用域下的方法。
PS3:知道為什么就知道怎么影響這個(gè)塊級(jí)作用域啦,引用傳遞可破,可知作用域變量遵循普通變量傳遞原則。

PS4:作用域鏈的非自己部分在函數(shù)對(duì)象被建立(函數(shù)聲明、函數(shù)表達(dá)式)的時(shí)候建立,而不需要等到執(zhí)行,這部分作用域鏈?zhǔn)庆o態(tài)的;當(dāng)函數(shù)執(zhí)行時(shí),建立一個(gè)自己當(dāng)次執(zhí)行的作用域,然后把這個(gè)作用域與前面的作用域鏈關(guān)聯(lián)起來(lái)