平時面試經常會遇到類似下面的這種題,而且千變萬化,讓人一個頭兩個,示例這道題算是稍微有點難度的了,這種題考查的是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)分析腳本的執行程序,也就是全域作用域下的代碼,
①創建全域物件GO(window)
②加載腳本代碼
③預編譯:依此找到var開頭的變數宣告,把變數加入到全域物件中;找到function開頭的函式宣告,也放到全域物件中,如果有相同的變數名或函式名,替換之前的;非宣告的陳述句不予理睬;
④解釋執行,變數賦值,函式呼叫
(2)分析每個函式的執行程序
①創建每個函式物件AO(Active Object)
②預編譯:創建作用域鏈;初始化arguments;初始化形參,系結arguments和形參;找到變數宣告加入到AO;找到函式宣告加入到AO;
③解釋執行
-----------------------------------------------------------------------------------------------------------------------------
具體分析上面的代碼:
全域作用域下預編譯階段: 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' }
有點亂哈,我寫的可能也不是很清楚,不過這個真的很重要,我也是想通過這種方式能讓自己加深印象,也希望有需要的人如果看到多少能提供一點幫助,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/170406.html
標籤:JavaScript
