某次在使用JQuery的.click()功能時,由於在callback function使用ES6的箭頭函式(Arrow Function),導致this所取得的參數並不是我期望的值(以為是這個click的element),後來研究ES6 this相關文章並實作測試後,才知道裡面有很多know how是如何運作的,真心建議有學js的要好好讀懂this的使用差異。
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寫法後
就可以正確取到li
的text()
值了
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()); // 輸出結果什麼都沒有
});
|
另外補充一下currentTarget
和target
的差別 : 參考 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