js的高級知識---詞法分析


詞法分析

詞法分析方法:

js運行前有一個類似編譯的過程即詞法分析,詞法分析主要有三個步驟:

  • 分析參數
  • 再分析變量的聲明
  • 分析函數說明

具體步驟如下:

  • 函數在運行的瞬間,生成一個活動對象(Active Object),簡稱AO
  • 分析參數
  1. 函數接收形式參數,添加到AO的屬性,並且這個時候值為undefine,例如AO.age=undefine
  2. 接收實參,添加到AO的屬性,覆蓋之前的undefine
  • 分析變量聲明,如var age;或var age=23;
  1. 如果上一步分析參數中AO還沒有age屬性,則添加AO屬性為undefine,即AO.age=undefine
  2. 如果AO上面已經有age屬性了,則不作任何修改
  • 分析函數的聲明,如果有function age(){}

把函數賦給AO.age ,覆蓋上一步分析的值

代碼例子1

這樣我們先通過一段代碼來理解詞法分析:

<script>
    function t1(age) {
        console.log(age);
        var age = 27;
        console.log(age);
        function age() {}
        console.log(age);
    }
    t1(3);
</script>

詞法分析階段:

 

  • 首先形成Active Object即AO對象

 

  • 第一步:分析形式參數

AO.age = undefine

傳入實參即對AO.age=undefine進行覆蓋:

AO.age = 3

 

  • 第二步:分析局部變量

存在var age = 27;

這個時候遵循如果AO.age存在值則不作任何修改,按照第一步分析的最后結果AO.age = 3,所以這里不作任何修改即:

AO.age = 3

 

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

因為函數中存在function age(){}函數

所以按照規則應該將函數賦值給AO.age覆蓋第二步分析的AO.age = 3即:

AO.age = function age(){}

執行階段

執行t1函數,到console.log(age)時,詞法分析的最后AO.age= function age(){},所以會打印:

function age(){}

 

var age=27;給age賦值27

到第二個console.log(age)這個時候age已經重新被賦值27,所以這個時候會打印:

27

 

function age() 並沒有調用所以並不會執行

 

到第三個console.log(age)這個時候age的值並沒有被再次修改,所以這個時候會打印:

27

運行js查看結果如下與我們分析的完全相符:

 

代碼例子2

 

<script>
    function t1(age) {
        var age;
        console.log(age);
        var age = 23;
        console.log(age);
        function age() {}
        console.log(age);
    }
    t1(22)
</script>

和上面的詞法分析過程一樣

詞法分析階段:

  • 首先形成Active Object即AO對象

 

  • 第一步:分析形式參數

AO.age = undefine

傳入實參即對AO.age=undefine進行覆蓋:

AO.age = 22

 

  • 第二步:分析局部變量

第一步中最后得到AO.age = 22

所以這里var age;以及var age =23 ,因為AO.age屬性已經存在值,所以這個時候遵循如果存在則不作任何修改,即:

AO.age = 22

 

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

因為函數中存在function age(){}函數

所以按照規則應該將函數賦值給AO.age覆蓋第二步分析的AO.age = 22即:

AO.age = function age(){}

 

執行階段

執行t1函數,到console.log(age)時,詞法分析的最后AO.age= function age(){},所以會打印:

function age(){}

 

var age=23;給age賦值23

到第二個console.log(age)這個時候age已經重新被賦值23,所以這個時候會打印:

23

 

function age() 並沒有調用所以並不會執行

 

到第三個console.log(age)這個時候age的值並沒有被再次修改,所以這個時候會打印:

23

 

運行js查看結果如下與我們分析的完全相符:

 

代碼例子3

<script>
    function t1(age) {
        var age;
        console.log(age);
        age = 23;
        console.log(age);
        function age() {
            console.log(age);
        }
        age();
        console.log(age)
    }
    t1(22)
</script>

詞法分析階段:

  • 首先形成Active Object即AO對象

 

  • 第一步:分析形式參數

AO.age = undefine

傳入實參即對AO.age=undefine進行覆蓋:

AO.age = 22

 

  • 第二步:分析局部變量

第一步中最后得到AO.age = 22,所以這里遵循,如果AO.age存在值則不作任何修改即:

AO.age = 22

 

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

因為函數中存在function age(){console.log(age)}函數

所以按照規則應該將函數賦值給AO.age覆蓋第二步分析的AO.age = 22即:

AO.age = function age(){console.log(age)}

 

執行階段

執行t1函數,到console.log(age)時,詞法分析的最后AO.age= function age(){console.log(age)},所以會打印:

function age(){console.log(age)}

 

age = 23,這個時候會覆蓋原來的function age(){console.log(age)},所以第二個console.log(age)會打印:

23

 

function age() 是一個函數表達式,所以不會做任何操作

 

age() 這個時候的age還是23,並不是函數表達式,所以這里會報錯

 

運行js查看結果如下與我們分析的完全相符:

 

 

這里的提示錯誤確實也是說age不是一個函數

代碼例子4

<script>
    function t1(age) {
        var age;
        console.log(age);
        function  age() {
            console.log(age);
        }
        age();
        console.log(age);
    }
    t1(23)
    
</script>

詞法分析階段:

 

  • 首先形成Active Object即AO對象

 

  • 第一步:分析形式參數

AO.age = undefine

傳入實參即對AO.age=undefine進行覆蓋:

AO.age = 23

 

  • 第二步:分析局部變量

第一步中最后得到AO.age = 23,所以這里遵循,如果AO.age存在值則不作任何修改即:

AO.age = 23

 

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

因為函數中存在function age(){console.log(age)}函數

所以按照規則應該將函數賦值給AO.age覆蓋第二步分析的AO.age = 23即:

AO.age = function age(){console.log(age)}

 

執行階段

執行t1函數,到console.log(age)時,詞法分析的最后AO.age= function age(){console.log(age)},所以會打印:

function age(){console.log(age)}

 

function age() 是一個函數表達式,所以不會做任何操作

 

age()這個時候age是一個函數表達式,這里會執行function age(){console.log(age)},這個時候函數里console.log(age),age沒有被修改所以還是function age(){console.log(age)},即打印:

function age(){console.log(age)}

 

最后一個console.log(age)這里的age沒有被修改還是function age(){console.log(age)},所以會打印:

function age(){console.log(age)}

 

運行js查看結果如下與我們分析的完全相符:

代碼例子5:

<script>
    function t1(age) {
        console.log(age);
        var age = function () {
            console.log(age)
        }
        age();
        console.log(age);
    }
    t1(23);
</script>

詞法分析階段:

  • 首先形成Active Object即AO對象

 

  • 第一步:分析形式參數

AO.age = undefine

傳入實參即對AO.age=undefine進行覆蓋:

AO.age = 23

 

  • 第二步:分析局部變量

第一步中最后得到AO.age = 23,所以這里遵循,如果AO.age存在值則不作任何修改即:

AO.age = 23

 

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

這里並沒有函數聲明表達式

所以最后分析的結果是:

AO.age = 23

 

執行階段

執行t1函數,到console.log(age)時,詞法分析的最后AO.age=23

所以第一個console.log(age)會打印

23

 

var age = function () {console.log(age)},這里將var = 23進行覆蓋這個時候age是一個函數表達式

 

age() 正好調用function () {console.log(age)},這個時候這個函數里的console.log(age),age並沒有修改還是一個函數表達式,所以會打印

function () {console.log(age)}

 

最后一個console.log(age)還是打印:

function () {console.log(age)}

 

運行js查看結果如下與我們分析的完全相符:

代碼例子6:

<script>
    function t1(age) {
        console.log(age);
        var age = function age() {
            console.log(age);
        }
        age();
        console.log(age);
    }
    t1(23);
</script>

代碼例子6和代碼例子5的分析基本一樣,結果也是一樣:

總結

總之,按照上述最開始寫的方法分析,都能分析出結果來


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM