JavaScript 執行過程



JavaScript整個執行過程,分爲兩個階段,代碼編譯階段和代碼執行階段node

  1. 1、編譯階段

編譯階段由編譯器執行,將代碼翻譯成可執行代碼,這個階段肯定做用域規則。數組

變量的預編譯只做聲明,不做初始化,初始化在執行時瀏覽器

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複製代碼
相關文章
相關標籤/搜索