js 執(zhí)行上下文笼吟,作用域咐鹤,變量內(nèi)存管理
JS中變量的定義在內(nèi)存中包括三個(gè)部分:
* 變量標(biāo)示 ∠肥邸(變量標(biāo)示存儲(chǔ)在內(nèi)存的棧區(qū))
* 變量值 (比如上面中的Str的值souvenir或者是obj1對(duì)象的指向堆區(qū)地址侨核,這個(gè)值也是存儲(chǔ)在棧區(qū))
* 對(duì)象 (對(duì)象存儲(chǔ)在堆區(qū))
也就是說,對(duì)于基本數(shù)據(jù)類型來說灌灾,只使用了內(nèi)存的棧區(qū)搓译。
執(zhí)行上下文堆棧
三種作用域
全局作用域、函數(shù)作用域锋喜、eval作用域(不常用些己,不做介紹)。
JavaScript中的運(yùn)行環(huán)境大概包括三種情況。
- 全局環(huán)境:JavaScript代碼運(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
當(dāng)javascript代碼文件被瀏覽器載入后涯冠,首先進(jìn)行上下文環(huán)境的準(zhǔn)備工作。會(huì)將全局的執(zhí)行上下文壓入執(zhí)行上下文棧的底部怀樟。
當(dāng)在全局上下文中調(diào)用執(zhí)行一個(gè)函數(shù)時(shí)功偿,程序流就進(jìn)入該被調(diào)用函數(shù)內(nèi),此時(shí)引擎就會(huì)為該函數(shù)創(chuàng)建一個(gè)新的執(zhí)行上下文往堡,并且將其壓入到執(zhí)行上下文棧械荷。棧頂永遠(yuǎn)都是當(dāng)前正在執(zhí)行的上下文,執(zhí)行完畢后該上下文就會(huì)從棧頂被彈出虑灰,直到回到全局的上下文吨瞎。全局上下文在瀏覽器窗口關(guān)閉后出棧。
注意:函數(shù)中穆咐,遇到return能直接終止可執(zhí)行代碼的執(zhí)行颤诀,因此會(huì)直接將當(dāng)前上下文彈出棧。
函數(shù)作用域中this的是在JS運(yùn)行時(shí)才能確定对湃,而全局作用域中的this在準(zhǔn)備上下文環(huán)境的時(shí)候就確定了(window)崖叫。
執(zhí)行上下文的建立過程
- 建立階段(發(fā)生在當(dāng)調(diào)用一個(gè)函數(shù)時(shí),但是在執(zhí)行函數(shù)體內(nèi)的具體代碼以前) ○ 建立變量拍柒,函數(shù)心傀,arguments對(duì)象,參數(shù) ○ 建立作用域鏈 ○ 確定this的值
- 代碼執(zhí)行階段: ○ 變量賦值拆讯,函數(shù)引用脂男,執(zhí)行其它代碼
建立階段:
- 建立variableObject對(duì)象: i. 為函數(shù)的參數(shù)和arguments對(duì)象賦值。建立arguments對(duì)象种呐,檢查當(dāng)前上下文中的參數(shù)宰翅,建立該對(duì)象下的屬性以及屬性值 ii. 檢查當(dāng)前函數(shù)聲明和變量。將函數(shù)名和變量名作為variableObject的一個(gè)屬性 存入爽室,屬性值都設(shè)為undefined汁讼。 為函數(shù)聲明直接賦值字符串
- 初始化作用域鏈 ○ 確定上下文中this的指向?qū)ο?/li>
執(zhí)行階段:
○ 執(zhí)行函數(shù)體中的代碼,一行一行地運(yùn)行代碼阔墩,給variableObject中的變量屬性賦值掉缺。
通俗的講,執(zhí)行上下文準(zhǔn)備工作就是在執(zhí)行代碼前戈擒,把將要用到的所有的變量都事先拿出來,有的直接賦值了艰毒,有的先用undefined占個(gè)空筐高。
//將全局變量的值設(shè)為undefined
console.log(a); //undefined
var a = 1;
//將window對(duì)象賦給this
console.log(this);
//將函數(shù)表達(dá)式的值設(shè)為undefined
console.log(fn1);//undefined
var fn1 = function(){
//……
}
//為函數(shù)聲明直接賦值
console.log(fn2); //輸出函數(shù)的代碼
function fn2(){
//……
}
//函數(shù)作用域
function fn3(b,c){
//確定自由變量的作用域
console.log(a);
//為局部變量賦上undefined
console.log(x);//undefined
var x = 123;
//為函數(shù)的參數(shù)賦值
console.log(b,c); //2,3
//為arguments賦值
console.log(arguments); //[2,3]
}
fn3(2,3);