iT邦幫忙

2022 iThome 鐵人賽

DAY 23
0
Modern Web

[學習筆記] 邊學邊寫 JavaScript 30天系列 第 23

[學習筆記] 邊學邊寫 JavaScript 30天 (23):Hoisting I

  • 分享至 

  • xImage
  •  

今天內容

  • 什麼是Hoisting(提升)?
  • 小練習來理解scope chain和hoisting
  • 從 ECMAScript 來看 hoisting 的原理(規則)

筆記

  • 什麼是Hoisting(提升)?

    console.log(b) //b is not defined -> 報錯
    //沒有宣告b的情況下,會直接報錯。
    
    console.log(b)
    var b = 10  //undefined
    //在後面做宣告時沒有報錯?
    //是因為宣告被Hoisting(提升),但賦值不會所以回傳undefined而不是10
    
    //可以想成是先宣告再賦值,像下面這樣:
    var b
    console.log(b)
    b = 10
    

    用在function也很常見,讓程式碼function位置不用都 一定 要在呼叫上面。
    可以先做呼叫,提高方便性。

    test()
    function test() {
      console.log(123)   //123
    }
    

    但用變數來宣告function又會報錯

    test()
    var test = function() {
      console.log(123)   //test is not a function -> 報錯
    }
    //這樣寫反而會報錯,因為只有宣告會提升
    //可以想成是先宣告再賦值,像下面這樣:
    var test
    test()
    test = function() {
      console.log(123)
    }
    
    function test() {
      console.log(a)
      var a = "local"
        function a() {
    
        }
    }
    test() //[Function: a]
    
    //function會優先於var,所以回傳Function: a
    //可以想成下面這樣:
    function test() {
        function a() {
    
        }
      console.log(a)
      a = "local"
    }
    test() //[Function: a],如果同時有兩個function a()後面會蓋掉前面的。
    
    function test(a) {
      console.log(a) //[Function: a]
      var a = 456
      function a() {
    
      }
    }
    test(123)
    //傳入參數也不會印出123或456,會以function a為優先。
    

    優先性順序:1.function -> 2.arguments -> 3.var

  • 用小練習來理解scope chain和hoisting(執行順序在最下面):

    var a = 1;
    function test(){
      console.log("1.", a);
      var a = 7;
      console.log("2.", a); 
      a++;
      var a;
      inner();
      console.log("4.", a);
      function inner(){
        console.log("3.", a);
        a = 30;
        b = 200;
      }
    }
    test();
    console.log("5.", a);
    a = 70;
    console.log("6.", a);
    console.log("7.", b);
    
  • 從 ECMAScript 來看 hoisting 的原理(規則)
    規範沒有提到Hoisting但有講到Execution Contexts和Variable Instantiation,從這兩個來看。

    • Execution Contexts
      在執行的時候functuon會依執行順序疊加在global上面,最上面的會先執行,執行完就消失,隨著程式碼會反覆堆高與減少,直到最底下的global執行完也等同整個程式執行完。如圖示:

      圖片來自於影片與Huli文章,該文章也是引用自freecodecamp

    • Variable Instantiation

      Every execution context has associated with it a variable object.
      把它想成每個function會有一個object來存變數

      function test() {
        var a = 1
      }
      
      VariableObject {
        a: 1
      }
      //VariableObject{}不是真實寫出來的,只是一個想成有這樣的位置存放function的值
      

      當傳入值的時候,會幫參數初始化。

        VariableObject {
          a: 123        // 只有傳一個參數a:123
          b: undefined  // b初始值會undefined
        }
        function test(a, b) {
      
        }
        test(123)  
      

      當test內有function a 存在時傳進去的參數123會優先被取代

      VariableObject {
        a: 123  
        b: undefined //b從undefined變成function
      }
      function test(a, b) {
        function b() {
      
        }
      }
      test(123)
      

      對變數的宣告,重覆的值不會被改變,沒有的才會被初始成undefined

      VariableObject {
        a: 123        //已經取得參數值,不會因為function b裡的var a=10而被改變
        b: function   //已經是function b,不會因為function b裡的var b=20而被改變
        c: undefined  //原本就沒有的才會被放進去。並給初始值undefined
      }
      function test(a, b) {
        function b() {
          var a = 10
          var b = 20
          var c = 30
        }
      }
      test(123)
      

      後面沒有再節錄規範原文,是直接看影片範例來理解。更詳細說明可以看參考資料Huli文章。


今天先講前半段,明天再繼續。
小題目解答先簡單放執行順序,明天再從執行環境的角度來重新理解。


參考資料


上一篇
[學習筆記] 邊學邊寫 JavaScript 30天 (22):變數的Scope
下一篇
[學習筆記] 邊學邊寫 JavaScript 30天 (24):Hoisting II
系列文
[學習筆記] 邊學邊寫 JavaScript 30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言