js 詞法分析,詞法做用域

先來看個常見的面試題以下:面試

var a = 10;
function test(){
    alert(a);  //undefined
    var a = 20;
    alert(a); //20
}
test();

疑問:爲何呢?test()執行時,雖然a=20沒有賦值,可是父級做用域裏是有a=10的,不該該是undefined呀,js是按順序執行的,此時的var num = 20;根本沒有執行,因此應該是10!!你是否是也是這麼認爲的,就和我當初同樣???函數

分析:衆所周知,js代碼是自上而下執行的,JavaScript並非傳統的塊級做用域,而是函數做用域。JavaScript引擎會在代碼執行前進行詞法分析,因此事實上,js運行分爲此法分析和執行兩個階段。code

JavaScript代碼運行前有一個相似編譯的過程即詞法分析,詞法分析主要有三個步驟:對象

  • 分析參數ip

  • 再分析變量的聲明作用域

  • 分析函數聲明io

具體步驟以下:編譯

函數在運行的瞬間,生成一個活動對象(Active Object),簡稱AOfunction

第一步:分析參數:test

  1. 函數接收形式參數,添加到AO的屬性,而且這個時候值爲undefined,即AO.name=undefined

  2. 接收實參,添加到AO的屬性,覆蓋以前的undefined

第二步:分析變量聲明:如var name;或var name='mary';

  1. 若是上一步分析參數中AO尚未name屬性,則添加AO屬性爲undefined,即AO.name=undefined

  2. 若是AO上面已經有name屬性了,則不做任何修改

第三步:分析函數的聲明:

若是有function name(){}把函數賦給AO.name ,覆蓋上一步分析的值

分析下面這個栗子:

1.var a = 10;
2.function test(a){
3.    alert(a);           //function a (){}
4.    var a = 20;
5.    alert(a);           //20
6.    function a (){}
7.    alert(a);           //20
8.    }
9.
10.test(100);

詞法分析:

第一步,分析函數參數:

形式參數:AO.a = undefined
 接收實參:AO.a = 100

第二步,分析局部變量:

第4行代碼有var a,可是此時已有AO.a = 100,因此不作任何修改,即AO.a = 100

第三步,分析函數聲明:

第6行代碼有函數a,則將function a(){}賦給AO.a,即AO.a = function a(){}

執行代碼時:

第3行代碼運行時拿到的a時詞法分析後的AO.a,即AO.a = function a(){};
第4行代碼:將20賦值給a,此時a=20;
第5行代碼運行時a已經被賦值爲20,結果20;
第6行代碼是一個函數表達式,因此不作任何操做;
第7行代碼運行時還是20;

ps:

1.var a = 10;
2.function test(a){
3.    var a;               //證實詞法分析第二步。
4.    alert(a);           //100
5.    a = 20;
6.    alert(a);           //20
7.}
7.test(100);

ps:

var a = 10;
function test(a){
    alert(a);         //100
    var a = 20;
    alert(a);         //20
    a = function(){}        //是賦值,只有在執行時纔有效
    alert(a);         //function(){}
}
test(100);

ps:(執行結果同上)

var a = 10;
function test(a){
    alert(a);                //100
    var a = 20;
    alert(a);                //20
    var a = function(){}        //是賦值,只有在執行時纔有效
    alert(a);                //function(){}
}
test(100);

補充說明:函數聲明與函數表達式

//函數聲明
function a(){
}
//函數表達式
var b = function(){
}

a和b在詞法分析時,區別:

a在詞法分析時,就發揮做用;
b只有在執行階段,才發揮做用。

詞法做用域

所謂詞法做用域是說,其做用域爲在定義時(詞法分析時)就肯定下來的,而並不是在執行時肯定。白話就是在函數未執行前,函數執行的順序已經被肯定,而不是相似JAVA同樣,是在執行前根本不知道執行順序。

相關文章
相關標籤/搜索