平時面試常常會遇到相似下面的這種題,並且變幻無窮,讓人一個頭兩個。示例這道題算是稍微有點難度的了,這種題考查的是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' }
有點亂哈,我寫的可能也不是很清楚,不過這個真的很重要,我也是想經過這種方式能讓本身加深印象,也但願有須要的人若是看到多少能提供一點幫助。