先來一段demo:
var x = 1; //全局變量x
function A(y) {
var x = 2; //局部變量x
function B(z) {
console.log(x+y+z);
}
return B;
}
var C = A(1);
C(1);
- 全局初始化
JS引擎在進入一段可執(zhí)行的代碼時尼变,需要完成以下三個初始化工作:
- 創(chuàng)建一個全局對象(Global Object)幢哨,這個對象全局只存在一份惶我,它的屬性在任何地方都可以訪問,它的存在伴隨著應用程序的整個生命周期裂允。全局對象在創(chuàng)建時缕棵,將Math孵班,String,Date招驴,document等常用的JS對象作為其屬性篙程。由于這個全局對象不能通過名字直接訪問,因此還有另一個屬性window别厘,并將window指向了自身虱饿,這樣就可以通過window訪問這個全局對象了/用偽代碼模擬全局對象的答題結構如下:
//創(chuàng)建一個全局對象
var globalObject = {
Math: {},
String: {},
Date: {},
document: {},//DOM操作
...
window: this,//window屬性指向自身
}
- JS引擎需要構建一個執(zhí)行環(huán)境(Execution Context Stack),與此同時,也要創(chuàng)建一個全局執(zhí)行環(huán)境(Execution Context)EC触趴,并將這個全局執(zhí)行環(huán)境EC壓入執(zhí)行環(huán)境棧中氮发。執(zhí)行環(huán)境棧的作用時為了保證程序能夠按照正確的順序被執(zhí)行。在js中冗懦,每個函數(shù)都有自己的執(zhí)行環(huán)境爽冕,當執(zhí)行一個函數(shù)時,該函數(shù)的執(zhí)行環(huán)境就會被推入執(zhí)行環(huán)境棧的頂部并獲取執(zhí)行權披蕉。當這個函數(shù)執(zhí)行完畢颈畸。它的執(zhí)行環(huán)境又從這個棧的頂部被刪除,并把執(zhí)行權還給之前執(zhí)行環(huán)境没讲。偽代碼模擬執(zhí)行環(huán)境棧和EC的關系:
var ECstack = [];//定義一個執(zhí)行環(huán)境棧眯娱,類似于數(shù)組
var EC = {}; //創(chuàng)建一個執(zhí)行空間,
ECstack.push(EC);//進入函數(shù)爬凑,壓入執(zhí)行環(huán)境
ECstack.pop(EC);//return 后徙缴,刪除執(zhí)行環(huán)境
- JS引擎創(chuàng)建一個與EC關聯(lián)的全局變量對象(Varibale Object)VO,并把VO指向全局對象嘁信,VO不僅包含了全局對象的原有屬性于样,還包括在全局定義的變量x和函數(shù)A坠陈,與此同時苛聘,在定義函數(shù)A的時候而钞,還為A添加了一個內(nèi)部屬性scope栽渴,并將scope指向了VO茉继。每個函數(shù)在定義的時候轧葛,都會創(chuàng)建一個與之關聯(lián)的scope屬性纳本,scope總是指向定義函數(shù)時所在的環(huán)境苔可。此時ECstack結構如下:
ECStack = [//執(zhí)行環(huán)境棧
EC(G) = { //全局執(zhí)行環(huán)境
VO(G):{ //定義全局變量對象
... //包含全局對象原有的屬性
x = 1; //定義變量x
A = function(){};
A[[scope]] = this;//定義A的scope,并賦值為vo本身
}
}
];
執(zhí)行一個函數(shù)啄刹,會發(fā)生什么涮坐?
function say() {
let str = 'hello world'
console.log(str)
}
- 創(chuàng)建函數(shù),過程:
- 開辟一個新的堆內(nèi)存
- 創(chuàng)建函數(shù)say誓军,把這個函數(shù)體中的代碼放在這個堆內(nèi)存中袱讹。(字符串形式)
- 在當前上下文中聲明say函數(shù)(變量),函數(shù)聲明和定義會提升到最前面
- 把開辟的堆內(nèi)存的地址賦值給函數(shù)名say
- 執(zhí)行函數(shù):
- 形成一個供代碼執(zhí)行的環(huán)境昵时,也是一個棧內(nèi)存捷雕。
- 將存儲的字符串復制一份到新開辟的棧內(nèi)存中,使其變?yōu)檎嬲腏S代碼壹甥。
- 先對形參進行賦值救巷,再進行變量提升。
- 在這個新開辟的作用域中自上而下執(zhí)行句柠。