回到文章列表

    [JS201 筆記] 先學完物件導向,學 this 才有意義

    TWGD / 2019-01-08 / 閱讀時間約 2 分鐘

    這是 Lidemy 課程:[JS201] 進階 JavaScript:那些你一直搞不懂的地方:先學完物件導向,學 this 才有意義 課程筆記。

    如果有人不小心看到,請不要太嚴格,這只是我上課的隨筆筆記XD 若有錯誤,請不要吝嗇糾正我,謝謝~


    this 的意義?

    this 在物件導向裡面使用,意義是指向指定的 instance。

    非物件導向下的 this 預設值是什麼?

    在不同環境底下,預設值不同 ( 非嚴格模式 ):

    function test() {
      console.log(this)
    }
    
    test()
    // node.js 裡面,this 是 global
    // 在瀏覽器裡面,this 預設是 window

    嚴格模式:

    'use strict' // 加上這段程式碼,使用嚴格模式
    
    function test() {
      console.log(this)
    }
    
    test() // undefined
    // 在 node.js 或瀏覽器,this 都是 undefined

    dom 操作的 this:

    document.querySelector('.btn').addEventListener('click', function () {
      console.log(this)
    })
    // 結果會是 click 的對象

    用 call 與 apply,呼叫 function:

    用法:

    func.call(context, p1, p2, p3)
    // 第一個參數傳的值就是 this
    // 後面依序傳 func 的參數
    
    func.apply(context, [p1, p2, p3])
    // 只接收兩個參數
    // 第一個參數傳的值就是 this
    // 第二個參數傳一個 func 的參數陣列
    'use strict'
    
    function test(a, b, c) {
      console.log(this)
      console.log(a, b, c)
    }
    
    test.call(123, 1, 2, 3)
    // 123
    // 1 2 3
    
    test.apply(123, [1, 2, 3])
    // 123
    // 1 2 3

    call() 與 apply() 的差異:

    • call():從第二個參數開始,依序傳入 function 的參數。
    • apply():只接收兩個參數。第二個參數傳一個 function 的參數陣列。

    強制綁定 this:bind

    強制綁定之後,無論用什麼呼叫方法,this 都不會改變。

    'use strict'
    
    const obj = {
      a: 123,
      test: function () {
        console.log(this)
      },
    }
    
    // 強制綁定:bind() 裡面傳什麼,this 就會是什麼
    const bindTest = obj.test.bind(obj)
    bindTest() // 印出的會是 obj
    bindTest.call('hahaha') // 印出的還是 obj
    bindTest.apply('lalala') // 印出的依然是 obj

    bind() 與 call()、apply() 的差異:

    • bind():綁定好之後,回傳一個 function
    • call()apply():直接呼叫 function。

    arrow function 的 this

    特別注意:arrow function 的 this 與呼叫的方法沒有關係,只與『如何定義』有關係。 this 的值會是定義 function 那個地方的 this 值。

    比較:

    class Test {
      run() {
        console.log('run test:', this)
        setTimeout(function () {
          // 這裡使用 function(){}
          console.log(this)
        }, 100)
      }
    }
    
    const t = new Test()
    t.run()
    // run test: Test {}
    // window (瀏覽器預設值)
    class Test {
      run() {
        console.log('run test:', this)
        setTimeout(() => {
          // 這裡使用 arrow function
          console.log(this)
        }, 100)
      }
    }
    
    const t = new Test()
    t.run()
    // run test: Test {}
    // Test {}