淺談javascript引擎執行代碼的步驟-(2019-2)

平時面試常常會遇到相似下面的這種題,並且變幻無窮,讓人一個頭兩個。示例這道題算是稍微有點難度的了,這種題考查的是JavaScript引擎執行代碼的步驟。面試

b = 'cba';
function a(a, a){
    console.log(a);
    console.log(b);
    var b = 'abc';
    
    a();
    function a(){
        console.log(a);
        console.log(b); 
    }
}
a(5,10);

先上理論:函數

(1)分析腳本的執行過程,也就是全局做用域下的代碼。spa

①建立全局對象GO(window)code

②加載腳本代碼對象

③預編譯:依此找到var開頭的變量聲明,把變量加入到全局對象中;找到function開頭的函數聲明,也放到全局對象中,若是有相同的變量名或函數名,替換以前的;非聲明的語句不予理睬;blog

④解釋執行,變量賦值,函數調用ip

(2)分析每一個函數的執行過程作用域

①建立每一個函數對象AO(Active Object)io

②預編譯:建立做用域鏈;初始化arguments;初始化形參,綁定arguments和形參;找到變量聲明加入到AO;找到函數聲明加入到AO;console

③解釋執行

-----------------------------------------------------------------------------------------------------------------------------

具體分析上面的代碼:

全局做用域下預編譯階段:
b = 'cba';//忽略,既不是變量聲明,也不是函數聲明
function a(a, a){//function開頭的函數聲明,GO加入函數a,函數體忽略
    console.log(a);
    console.log(b);
    var b = 'abc';
    a();
    function a(){
        console.log(a); 
        console.log(b); 
    }
}
a(5,10);

全局做用域下解釋執行:
b = 'cba';//GO中加入變量b,且賦值爲'cba'
function a(a, a){
    console.log(a);
    console.log(b);
    var b = 'abc';
    a();
    function a(){
        console.log(a); 
        console.log(b); 
    }
}
a(5,10);//執行函數a,而後生成a的AO

函數a的預編譯階段:
初始化arguments;
初始化形參,兩個形參名都爲a,後賦的值會替換先賦的值,a先賦值爲5,後賦值爲10,因此此時變量a爲10;
console.log(a);//不是變量聲明,忽略
console.log(b);//忽略
var b = 'abc';//是變量聲明,將變量b加入到AO,值爲undefined
a();//忽略
//函數聲明,函數a與形參a同名,替換以前的a=10,此時a爲function
function a(){
    console.log(a); 
    console.log(b); 
}

函數a解釋執行階段:
console.log(a);//輸出function
console.log(b);//輸出undefined
var b = 'abc';//變量b賦值'abc'
a();//執行,此處省略分析子函數a的預編譯過程
function a(){
    console.log(a); //子函數a的AO中沒有變量a,向父函數a中尋找,因此輸出function
    console.log(b); //子函數a的AO中沒有變量b,向父函數a中尋找,全部輸出'abc'
}

有點亂哈,我寫的可能也不是很清楚,不過這個真的很重要,我也是想經過這種方式能讓本身加深印象,也但願有須要的人若是看到多少能提供一點幫助。

相關文章
相關標籤/搜索