javascript數(shù)據(jù)類型與變量類型如下圖:
javascript數(shù)據(jù)最铁、變量類型.png
執(zhí)行上下文(Execution Context)
每當(dāng)控制器轉(zhuǎn)到可執(zhí)行代碼的時(shí)候棵里,就會(huì)進(jìn)入一個(gè)執(zhí)行上下文,執(zhí)行上下文可以理解為當(dāng)前代碼的執(zhí)行環(huán)境禾进,他會(huì)形成一個(gè)作用域豁跑。javascript中的運(yùn)行環(huán)境大概包括三種:
- 全局環(huán)境:js代碼運(yùn)行起來首先會(huì)進(jìn)入該環(huán)境。
- 函數(shù)環(huán)境:當(dāng)函數(shù)被調(diào)用執(zhí)行時(shí),會(huì)進(jìn)入當(dāng)前函數(shù)中的執(zhí)行代碼艇拍。
- eval(不建議使用狐蜕,可忽略)
- 因此在一個(gè)javascript程序中,必定會(huì)產(chǎn)生多個(gè)執(zhí)行上下文卸夕,js引擎會(huì)以棧的方式處理他們层释,這個(gè)棧我們稱其為調(diào)用棧
(call stack)
。棧底永遠(yuǎn)是全局上下文(Global Context)
快集,而棧頂就是當(dāng)前執(zhí)行的上下文贡羔。在代碼執(zhí)行過程中,遇到上面3中情況个初,都會(huì)生成一個(gè)執(zhí)行上下文乖寒,放入棧中,而處于棧頂?shù)纳舷挛膱?zhí)行完畢之后院溺,就會(huì)自動(dòng)出棧楣嘁。全局上下文會(huì)在瀏覽器窗口關(guān)閉后出棧。 - 關(guān)于上下文的總結(jié):
- 單線程
- 同步執(zhí)行珍逸,只有棧頂?shù)纳舷挛奶幱趫?zhí)行中逐虚,其他上下文需要等待
- 全局上下文只有唯一的一個(gè),它在瀏覽器關(guān)閉時(shí)出棧
- 函數(shù)的執(zhí)行上下文的個(gè)數(shù)沒有限制
- 每次某個(gè)函數(shù)被調(diào)用谆膳,就會(huì)有個(gè)新的執(zhí)行上下文為其創(chuàng)建叭爱,即使是調(diào)用的自身函數(shù),也是如此摹量。
變量和函數(shù)在內(nèi)存中的展示
- 基本數(shù)據(jù)類型是直接存在棧內(nèi)存中涤伐,而引用類型是在棧中存儲(chǔ)了指針,該指針指向了堆中該實(shí)體的起始地址缨称。當(dāng)解釋器尋找引用值時(shí)凝果,會(huì)首先檢索其在棧中的地址,取得地址后從堆中獲得實(shí)體睦尽。基本數(shù)據(jù)類型按照值來訪問器净,引用數(shù)據(jù)類型按照引用來訪問。
image.png
預(yù)解析(也稱聲明提升):
- 在ES6之前当凡,變量使用
var
聲明山害,會(huì)存在變量的預(yù)解析,函數(shù)也有預(yù)解析沿量。所謂預(yù)解析浪慌,就是在當(dāng)前作用域中,javascript代碼執(zhí)行之前朴则,瀏覽器首先會(huì)默認(rèn)的把所有帶var
和function
聲明的變量進(jìn)行提前聲明或者定義权纤。 - 聲明和定義
var num = 1;
//聲明: var num:告訴瀏覽器在全局作用域有一個(gè)num變量
//定義:num = 1 ;定義就是給變量進(jìn)行賦值
-
var聲明的變量和function聲明的函數(shù)在預(yù)解析的區(qū)別
var
聲明的變量和function聲明的函數(shù)在預(yù)解析的時(shí)候有區(qū)別,var
聲明的變量在預(yù)解析的時(shí)候只是提前的聲明汹想,function
聲明的函數(shù)在預(yù)解析的時(shí)候會(huì)提前聲明并且會(huì)同時(shí)定義外邓。也就是說var聲明的變量和function聲明的函數(shù)的區(qū)別是在聲明的同時(shí)有沒同時(shí)進(jìn)行定義。下面舉個(gè)例子:console.log(num); //undefined console.log(test); //test函數(shù)體古掏,而不是undefined var num = 1; function test() { console.log('test'); } console.log(num); //1 console.log(test); //test函數(shù)體损话,沒有返回值,所以會(huì)在輸出一個(gè)undefined
image.png- 變量對(duì)象的創(chuàng)建過程為:先創(chuàng)建
arguments
對(duì)象槽唾,然后檢查function
函數(shù)聲明創(chuàng)建屬性丧枪,最后檢查var
變量聲明創(chuàng)建屬性。因此function聲明會(huì)比var聲明優(yōu)先級(jí)更高一點(diǎn)夏漱,下面舉個(gè)例子:
console.log(num); //打印出了function num 而不是undefined豪诲。 var num = 1; function num() { console.log('test'); }
image.png?
預(yù)解析的順序
- 程序開始先預(yù)解析語法顶捷,標(biāo)點(diǎn)符號(hào)是否有誤挂绰,解析內(nèi)存是否可容納,解析變量……直到解析無誤了服赎,才開始按正常的流程順序走葵蒂。如果沒有預(yù)解析順序,直接按流程順序走重虑,可能程序執(zhí)行到最后一個(gè)函數(shù)践付,發(fā)現(xiàn)了語法錯(cuò)誤,才開始報(bào)錯(cuò)缺厉,那性能要有多差坝栏摺!
- 順序內(nèi)容:
- 文件內(nèi)引用的
<script>
塊依次解析提针,從上到下連成一片命爬。 - 每個(gè)
<script>
塊內(nèi)的function
,var
解析到本塊的開頭辐脖。(先解析function
饲宛,再解析var
) - 依次解析每個(gè)環(huán)境,將
function嗜价,var
解析到環(huán)境的開頭艇抠。
?
- 變量對(duì)象的創(chuàng)建過程為:先創(chuàng)建
reference--JavaScript中的預(yù)解析