回到文章列表

[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 {}