js 函數提高和變量提高

 

總結:html

函數提高比變量提高優先級高!

詞法分析

詞法分析方法:

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 ,覆蓋上一步分析的值post

代碼例子1

這樣咱們先經過一段代碼來理解詞法分析:spa

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

詞法分析階段:

 等價於:

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

  

  • 首先造成Active Object即AO對象

 

  • 第一步:分析形式參數

AO.age = undefinecode

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

AO.age = 3對象

 

  • 第二步:分析局部變量

存在var age = 27;blog

這個時候遵循若是AO.age存在值則不做任何修改,按照第一步分析的最後結果AO.age = 3,因此這裏不做任何修改即:ip

AO.age = 3it

 

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

由於函數中存在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>
複製代碼

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

詞法分析階段:

等價於:

<script>
    function t1(age) {
        var age=  function () {};
        console.log(age);
        var age = 23;
        console.log(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>
複製代碼

詞法分析階段:

等價於:

<script>
    function t1(age) {
        var age=  function age() {  //函數表達式
            console.log(age);
        };
        console.log(age); //輸出age函數
        age = 23;    
        console.log(age);   //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=function  age() {
            console.log(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);   //23
        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的分析基本同樣,結果也是同樣:

總結

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

全部的努力都值得期許,每一份夢想都應該灌溉!
相關文章
相關標籤/搜索