JS let/for循環(huán)問(wèn)題/作用域/上下文環(huán)境隨筆

遇到這么個(gè)題,結(jié)果因吹絲挺
試了一下這樣結(jié)果更因吹絲挺了
???什么鬼???

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


顯然setTimeout里的1是在程序執(zhí)行完畢后才執(zhí)行的

所以就不難理解為什么第一張圖會(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)這段代碼的作用域鏈也不相同。
好煩啊終于搞定了,這樣就可以證明在使用let的情況下每次循環(huán)中聲明的回調(diào)的作用域鏈被固定下來(lái)啦
  • 當(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í)作用域,互不干擾。

var循環(huán)
let循環(huán)

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


如何影響塊級(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)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容