先說說棧吧!
棧的執(zhí)行順序是先進(jìn)后出,后進(jìn)先出!
執(zhí)行上下文棧
執(zhí)行全局代碼和函數(shù)時,都會產(chǎn)生一個環(huán)境,叫做執(zhí)行上下文。一開始打開頁面的時候。全局環(huán)境(全局執(zhí)行上下文)就會入棧。當(dāng)執(zhí)行到函數(shù)時,該函數(shù)也會產(chǎn)生一個執(zhí)行環(huán)境,并入棧。(如果函數(shù)里包含另一個函數(shù),同理)等該函數(shù)執(zhí)行完了,就將該函數(shù)的執(zhí)行環(huán)境彈出棧,返回全局上下文環(huán)境。
舉個例子
當(dāng)加載<script>中的代碼時,全局執(zhí)行環(huán)境入棧
當(dāng)執(zhí)行到 10 行的時候,sayHello執(zhí)行環(huán)境入棧
sayHello中還有一個sayWorld環(huán)境,執(zhí)行到該環(huán)境(第 8 行)的時候,sayWorld執(zhí)行環(huán)境入棧
sayWorld執(zhí)行完畢后,就彈棧,回到sayHello執(zhí)行環(huán)境,再sayHello執(zhí)行完畢后,彈棧。回到全局執(zhí)行環(huán)境。關(guān)閉瀏覽器的時候,全局執(zhí)行環(huán)境也彈出棧!
整個入棧彈棧過程
執(zhí)行上下文
什么是執(zhí)行上下文。個人理解為代碼的執(zhí)行環(huán)境。不同的代碼有不同的執(zhí)行環(huán)境。
一個執(zhí)行上下文的生命周期分為兩階段。創(chuàng)建階段和代碼執(zhí)行階段
創(chuàng)建階段是為該環(huán)境的代碼執(zhí)行先做好準(zhǔn)備。
創(chuàng)建階段:包括創(chuàng)建變量對象、建立作用域鏈?、確定this的指向
1、創(chuàng)建變量對象:
① 建立arguments對象和參數(shù)的賦值。
②函數(shù)聲明:也就是使用function關(guān)鍵字聲明的函數(shù)。在變量對象中以函數(shù)名建立一個屬性,屬性值為指向該函數(shù)所在內(nèi)存地址的引用。如果函數(shù)名的屬性已經(jīng)存在,那么該屬性將會被新的引用所覆蓋。
③變量聲明:檢查當(dāng)前上下文中的變量聲明,每找到一個變量聲明,就在變量對象中以變量名建立一個屬性,屬性值為undefined。如果該變量名的屬性已經(jīng)存在,為了防止同名的函數(shù)被修改為undefined,則會直接跳過,原屬性值不會被修改。
舉個例子:
這里作用域鏈和this的指向先不講
然后就是執(zhí)行階段了。
執(zhí)行的時候,若代碼需要獲取變量或函數(shù)或?qū)ο螅蜁阶兞繉ο笾腥ト。?br>若執(zhí)行到代碼賦值(如var eye = 2)就更行變量對象中同名變量的變量值!
在基本變量未執(zhí)行賦值的時候讀取變量,會取得undefined!
先這樣吧。