iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 23
5

箭頭函式的 this
這幾天看了很多關於函式中 this 的文章,但感覺還不是很懂 XDDD,今天要來跟著這個影片來學習傳統函式跟箭頭函式中 this 的差別,練練我的小腦袋!

如果想了解詳細關於 this 的介紹,以下好文推推歐 ^___^:

Huli:淺談 JavaScript 頭號難題 this:絕對不完整,但保證好懂
卡斯伯:JavaScript 的 this 到底是誰?
卡斯伯:箭頭函式 (Arrow functions)


傳統函式 vs. 箭頭函式

綁定的 this 不同

傳統函式:this 會依照呼叫的方法而定,並非宣告的時機
箭頭函式:this 會綁定到其定義時所在的物件


範例

我們有一個物件 rabbit,裡面記錄某隻兔子的姓名跟日常興趣,還有一個函式搭配 map() 方法用來 console.log出兔子的姓名跟興趣,如果用傳統函式的話就會這樣寫:

const rabbit = {
  name: '泡泡',
  daily: ['耍廢','放空','裝可愛'],
  printDaily: function() {
    this.daily.map(function(item){
      console.log(`${this.name} 每天都在 ${item}`);
    })
  }
}
rabbit.printDaily();

來看一下結果:
https://ithelp.ithome.com.tw/upload/images/20190924/20119924GbaMkBDQo5.png
邪門囉,我的泡泡不見了!
看來是 map() 方法中的 this.name 出了問題,這邊的 this 值是什麼呢?我們來確認一下:

const rabbit = {
  name: '泡泡',
  daily: ['耍廢','放空','裝可愛'],
  printDaily: function() {
    this.daily.map(function(item){
      console.log(this); // window 物件
    })
  }
}
rabbit.printDaily();

map() 裡的 this 綁定到了 window 物件。
原因是因為: 傳統函式宣告的位置並不會影響 this 指向的值,重要的是呼叫的方法,如果是純粹的呼叫傳統函式的話,無論放在什麼位置,這個 this 都會指向全域,而 map() 方法裡的函式,是 map() 方法內的回調函數,他是一個獨立函數,不是被當作物件的方法調用,這個時候這個獨立函數裡面的 this 就會指向 window 了。

那如果我們是在物件的方法中呼叫 this 的話呢?

const rabbit = {
  name: '泡泡',
  daily: ['耍廢','放空','裝可愛'],
  printDaily: function() {
    console.log(this); // rabbit 物件
  }
}
rabbit.printDaily();

這裡的 this 綁定到了 rabbit 物件。
原因是因為: 如果 function 是在物件下調用,那麼 this 則會指向此物件,無論 function 是在哪裡宣告。

所以在過去的作法,我們會另外宣告一個變數賦值 this 的值,像是這樣:

const rabbit = {
  name: '泡泡',
  daily: ['耍廢','放空','裝可愛'],
  printDaily: function() {
    let self = this;
    this.daily.map(function(item){
      console.log(`${self.name} 每天都在 ${item}`);
    })
  }
}
rabbit.printDaily();

來看看結果:
https://ithelp.ithome.com.tw/upload/images/20190924/20119924Re9q6wcUrT.png
這樣就可以成功取得泡泡的名稱囉!


箭頭函式作法

但如果我們把map() 方法內的函式改成箭頭函式呢?

const rabbit = {
  name: '泡泡',
  daily: ['耍廢','放空','裝可愛'],
  printDaily: function() {
    this.daily.map(item => {
      console.log(`${this.name} 每天都在 ${item}`) 
    })
  }
}
rabbit.printDaily();

console 畫面:
https://ithelp.ithome.com.tw/upload/images/20190924/20119924fHbsrQcbnn.png
哦!成功綁定到泡泡物件了!這是為什麼呢?
那是因為: 箭頭函式的 this 值會繼承他的父作用域,跟傳統函式「根據呼叫的方式而定」不同,箭頭函式是在定義時就被指定了,以後也不會隨著呼叫方法改變,所以我們這個例子中的 this 值就會調用他的父作用域的 this 值「泡泡物件」,所以我們就能正確得到泡泡的名稱囉!


所以我學到了

如果今天我想要函式中的 this 值綁定父作用域的 this 值、並且不希望他在調用時被改變時,那就可以使用箭頭函式囉!


有錯誤歡迎指正!謝謝!!

上一篇
Day22【ES6 小筆記】變數提升(Hoisting)與暫時死區(TDZ)
下一篇
Day24【ES6 小筆記】資料型別 Symbol 使用時機
系列文
透過 ESLint 練習 JavaScript ES630

1 則留言

0
阿展展展
iT邦好手 1 級 ‧ 2019-10-16 04:01:59

每天都在放空
/images/emoticon/emoticon07.gif

我要留言

立即登入留言