HTML

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<ul class="ex1">
  <li>aaa</li>
  <li>bbb</li>
  <li>ccc</li>
</ul>
<ul class="ex2">
  <li>111</li>
  <li>222</li>
  <li>333</li>
</ul>

當時的狀況

1
2
3
$(".ex1 li").click(() => { // 使用箭頭函式
  console.log($(this).text()); // 輸出結果什麼都沒有
});

後來改成ES5 function寫法後
就可以正確取到litext()值了

1
2
3
$(".ex1 li").click(function () { // 改用用傳統函式
  console.log($(this).text()); // 這樣就會輸出<li>裡的 text 值
});

那如果我還是想使用箭頭函式
並且在callback中取到這個event物件的值
那就配合使用event 參數 : 參考 JQuery: .click()
所以我們可以改成這樣

1
2
3
4
$(".ex1 li").click((event) => { // 使用箭頭函式
  let this = event.currentTarget;
  console.log($(this).text()); // 輸出結果什麼都沒有
});

另外補充一下currentTargettarget的差別 : 參考 JQuery: Event Object
currentTarget : $(“elenemt”) 這個物件
target : $(“elenemt”) 底下觸及的物件, ex: , $(“body”).click()後,若你click在div上,則event.target會是這個div底下所有包含的東西

根據上述問題整理一下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// 範例一
$(".ex1 li").click("eventData", (event) => {
  console.log(event.data); // eventData
  console.log(event.currentTarget); // li element
  console.log(this); // window object
  console.log(this === window); // true
  console.log(this.document === document); // true
});

// 範例二
$(".ex2 li").click("eventData2", function (event) {
  console.log(event.data); // eventData2
  console.log(event.currentTarget); // li element
  console.log(this); // li element
  console.log(this === event.currentTarget); // true
});

探討 this 問題

上面的問題解完後
還有一個 this 的問題需要深入探討

可參考這兩篇有關箭頭函式的文章

重點摘錄

  • 箭頭函式並沒有自己的 this
  • this 會往上找到最近的函數主體作為物件

範例一

1
2
3
4
5
6
7
8
<body>
    <button id="btn">send</button>
</body>
<script>
    document.getElementById('btn').onclick = () => { 
        console.log(this) 
    };
</script>
1
Window {parent: Window, opener: null, top: Window, length: 0, frames: Window, …}

this 往上找不到 function 的物件
然後加上箭頭函式並沒有自己的 this
所以找到全域 window (他應該是函數主體)

範例二

1
2
3
4
5
6
7
8
<body>
    <button id="btn">send</button>
</body>
<script>
    document.getElementById('btn').onclick = function () { 
        console.log(this) 
    };
</script>
1
<button id="btn">send</button>

this 往上找到最近 function 的函式主體
所以 this = button 物件

重要 => 箭頭函式裡的this會指向創造他的物件上

另外其他可參考的範例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
var auntie = {
  name: '漂亮阿姨',
  callName () { // 註: 傳統方法的簡寫
    setTimeout(() => {
      // 箭頭函式中會自動指向生成的物件上
      console.log(this); // this = auntie 這個物件
    }, 10);
  }
}
auntie.callName();

Summary

其實 javascript 的 this 因為 ES5 和 ES6 的版本
衍生出蠻多使用情況
其實我也要來回讀很多次才會懂
建議要自己下去開個 html 實作看看才會有深刻的感覺
網路上可以找到很多相關的文章 keyword : ES6 this

理解 ES6 this 後
就會比較清楚當初 jquery closure function 會出現 this 的物件錯誤
如果之後再遇到類似的狀況
其實只要發現 arrow function不行就換成傳統function
但網路上好像也有人建議說不要混搭
統一function寫法風格比較不會造成維護困難
arrow function能做到的,好像傳統 function 也都能做到
差別應該就是程式碼簡潔和設計概念

References