先說說棧吧!
棧的執(zhí)行順序是先進(jìn)后出,后進(jìn)先出!
執(zhí)行上下文棧
執(zhí)行全局代碼和函數(shù)時(shí),都會(huì)產(chǎn)生一個(gè)環(huán)境,叫做執(zhí)行上下文。一開始打開頁面的時(shí)候。全局環(huán)境(全局執(zhí)行上下文)就會(huì)入棧。當(dāng)執(zhí)行到函數(shù)時(shí),該函數(shù)也會(huì)產(chǎn)生一個(gè)執(zhí)行環(huán)境,并入棧。(如果函數(shù)里包含另一個(gè)函數(shù),同理)等該函數(shù)執(zhí)行完了,就將該函數(shù)的執(zhí)行環(huán)境彈出棧,返回全局上下文環(huán)境。

舉個(gè)例子

當(dāng)加載<script>中的代碼時(shí),全局執(zhí)行環(huán)境入棧

當(dāng)執(zhí)行到 10 行的時(shí)候,sayHello執(zhí)行環(huán)境入棧

sayHello中還有一個(gè)sayWorld環(huán)境,執(zhí)行到該環(huán)境(第 8 行)的時(shí)候,sayWorld執(zhí)行環(huán)境入棧

sayWorld執(zhí)行完畢后,就彈棧,回到sayHello執(zhí)行環(huán)境,再sayHello執(zhí)行完畢后,彈棧。回到全局執(zhí)行環(huán)境。關(guān)閉瀏覽器的時(shí)候,全局執(zhí)行環(huán)境也彈出棧!
整個(gè)入棧彈棧過程

執(zhí)行上下文
什么是執(zhí)行上下文。個(gè)人理解為代碼的執(zhí)行環(huán)境。不同的代碼有不同的執(zhí)行環(huán)境。
一個(gè)執(zhí)行上下文的生命周期分為兩階段。創(chuàng)建階段和代碼執(zhí)行階段
創(chuàng)建階段是為該環(huán)境的代碼執(zhí)行先做好準(zhǔn)備。
創(chuàng)建階段:包括創(chuàng)建變量對(duì)象、建立作用域鏈?、確定this的指向
1、創(chuàng)建變量對(duì)象:
① 建立arguments對(duì)象和參數(shù)的賦值。
②函數(shù)聲明:也就是使用function關(guān)鍵字聲明的函數(shù)。在變量對(duì)象中以函數(shù)名建立一個(gè)屬性,屬性值為指向該函數(shù)所在內(nèi)存地址的引用。如果函數(shù)名的屬性已經(jīng)存在,那么該屬性將會(huì)被新的引用所覆蓋。
③變量聲明:檢查當(dāng)前上下文中的變量聲明,每找到一個(gè)變量聲明,就在變量對(duì)象中以變量名建立一個(gè)屬性,屬性值為undefined。如果該變量名的屬性已經(jīng)存在,為了防止同名的函數(shù)被修改為undefined,則會(huì)直接跳過,原屬性值不會(huì)被修改。
舉個(gè)例子:


這里作用域鏈和this的指向先不講
然后就是執(zhí)行階段了。
執(zhí)行的時(shí)候,若代碼需要獲取變量或函數(shù)或?qū)ο螅蜁?huì)到變量對(duì)象中去??!
若執(zhí)行到代碼賦值(如var eye = 2)就更行變量對(duì)象中同名變量的變量值!
在基本變量未執(zhí)行賦值的時(shí)候讀取變量,會(huì)取得undefined!
先這樣吧。