JavaScript整個執行過程,分爲兩個階段,代碼編譯階段和代碼執行階段node
編譯階段由編譯器執行,將代碼翻譯成可執行代碼,這個階段肯定做用域規則。數組
變量的預編譯只做聲明,不做初始化,初始化在執行時瀏覽器
function語句定義的函數,不只聲明瞭函數名,並且函數體也進行了處理bash
2、執行階段函數
執行階段由引擎完成,主要任務是執行可執行代碼,執行上下文在這個階段建立。執行上下文也分爲建立階段和執行階段。ui
一、執行上下文this
執行上下文能夠理解爲當前代碼的執行環境,它會造成一個做用域。spa
二、三種類型翻譯
a、全局執行上下文:瀏覽器的全局對象是window對象,this指向這個全局對象code
b、函數執行上下文:存在無數個,只有在函數被調用的時候纔會被建立,每次調用函數都會建立一個新的執行上下文,函數上下文的變量對象初始化只包括 Arguments 對象。
c、Eval函數執行上下文:指運行在eval函數的代碼,不多用並且不建議使用。。
建立階段:
肯定this的值,也被成爲 This Binding;
This Binding
a、全局執行上下文中,this 指向全局對象,在瀏覽器中this 指向window對象,在nodejs中指向這個文件的module 對象。
b、函數執行上下文中,this的值取決於函數的調用方式。具體有:默認綁定、隱式綁定、顯式綁定、new綁定、箭頭函數。
例一:變量提高
foo(); // 報錯
var foo = function () {
console.log('foo1');
}
foo(); // foo1,foo從新賦值
var foo = function () {
console.log('foo2');
}
foo(); // foo2,foo從新賦值
複製代碼
例二:函數提高
foo(); // foo2
function foo() {
console.log('foo1');
}
foo(); // foo2
function foo() {
console.log('foo2');
}
foo(); // foo2
複製代碼
例三:聲明優先級,函數 > 變量
foo(); // foo2
var foo = function() {
console.log('foo1');
}
foo(); // foo1,foo從新賦值
function foo() {
console.log('foo2');
}
foo(); // foo1
複製代碼
須要注意的是同一做用域下存在多個同名函數聲明,後面的會替換前面的函數聲明。
3、執行上下文棧
由於JS引擎建立了不少的執行上下文,因此JS引擎建立了執行上下文棧(Execution context stack,ECS)來管理執行上下文。
當 JavaScript 初始化的時候會向執行上下文棧壓入一個全局執行上下文,咱們用 globalContext 表示它,而且只有當整個應用程序結束的時候,執行棧纔會被清空,因此程序結束以前, 執行棧最底部永遠有個 globalContext。
ECStack = [ // 使用數組模擬棧
globalContext
];複製代碼
當執行一個函數的時候,就會建立一個執行上下文,而且壓入執行上下文棧,當函數執行完畢的時候,就會將函數的執行上下文從棧中彈出。
var scope = "global scope";
function checkscope(){
var scope = "local scope1";
function f(){
console.log(scope);
}
return f(); //執行
}
checkscope();
var scope = "global scope";
function checkscope(){
var scope = "local scope22";
function f(){
console.log(scope);
}
return f; //返回function
}
checkscope()();複製代碼
第一段代碼:
ECStack.push(<checkscope> functionContext);//執行checkscope
ECStack.push(<f> functionContext);//執行f
ECStack.pop();//彈出f
ECStack.pop();//彈窗checkscope複製代碼
第二段代碼:
ECStack.push(<checkscope> functionContext);//執行checkscope
ECStack.pop();//返回function
ECStack.push(<f> functionContext);//執行f
ECStack.pop();//返回f複製代碼