平時面試經常會遇到類似下麵的這種題,而且千變萬化,讓人一個頭兩個。示例這道題算是稍微有點難度的了,這種題考查的是JavaScript引擎執行代碼的步驟。 先上理論: (1)分析腳本的執行過程,也就是全局作用域下的代碼。 ①創建全局對象GO(window) ②載入腳本代碼 ③預編譯:依此找到var開頭 ...
平時面試經常會遇到類似下麵的這種題,而且千變萬化,讓人一個頭兩個。示例這道題算是稍微有點難度的了,這種題考查的是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' }
有點亂哈,我寫的可能也不是很清楚,不過這個真的很重要,我也是想通過這種方式能讓自己加深印象,也希望有需要的人如果看到多少能提供一點幫助。