一次搞懂 JavaScript 的 this
前言
在FB直播看到 姚偉揚 老師再說明javascript各種 this 的分辨,在此紀錄各種案例。
議程重點
- 一般函式的 this
- ES6 箭頭函式的 this
- Vue 組件的 this
- bind/apply/call 的 this
一般函式的this
this
主要是 看函式(function)怎麼執行 的,下列為常見的分辨的方法
- 直接執行 → global
- 作為物件的成員函式執行 → 該物件
- 作為 DOM 事件偵聽函式 → 該 DOM
- 作為建構函式 → 建構出來的實例
下列為各種this的判斷
範例1
1 | function a(){ |
範例2
1 | function a(){ |
範例3
1 | const obj = { |
因為 b()
是直接執行,並不是以 obj.b()
方式執行。
範例4
1 | <button id='btn'>btn</button> |
1 | function a(){ |
範例5
1 | <button id='btn'>btn</button> |
1 | function a(){ |
因為 a()
是直接執行。
1 | function a(){ |
範例6
1 | <button id='btn'>btn</button> |
1 | const obj = { |
1 | btn.addEventListener('click', function(){ |
範例7
1 | <button id='btn'>btn</button> |
1 | function a(){ |
1 | btn.addEventListener('click', function(){ |
可注意觀察 範例5~7 程式碼之間有些微的不同,所造成的this有所不一樣。
善用的方式
另外一種思考的方式,我們在寫物件內的函式時,為了確保 this 能夠正確運作會先將它賦予在另一個變數上 (that, self, vm…)。
1 | var auntie = { |
箭頭函式的 this
口訣:箭頭函式裡面的this 等於 外面的this
白話文:箭頭函式裡的this 主要是依據 外層函式(function)裡的this 是什麼就跟著是什麼。
規則
1 | function x(){ |
範例1
1 | <button id='btn'>btn</button> |
1 | const a = () => { |
範例2
1 | const obj = { |
範例3
1 | <button id='btn'>btn</button> |
1 | function a() { |
與 一般函式的範例3 有點類似,雖然 b()
都是直接執行,
不過因為箭頭函式裡的this 主要是依據 外層函式(function)裡的this 是什麼就跟著是什麼,
所以 a()
的 this
是 DOM元素,所以這裡的 b()
的 this
也會跟著是 DOM元素。
範例4
Q:包了好幾層的箭頭函數的 this 也是指向 windows 嗎?
A:從 c()
一層撥一層 直到 function a()
,再參照 a()
的 this
是指向誰。
1 | function a(){ |
Vue 組件的 this
全部皆指向 vue實例 本身
範例1
1 | var vm = new Vue({ |
範例2
1 | var vm = new Vue({ |
範例3
若是 vue的建立是包在 函數
裡面時,使用 箭頭函數
,則this要看外層函數的this。
1 | function init() { |
如果在vue裡,寫箭頭函式要使用this的話,因為vue是物件,而不是函式,
此時箭頭函式裡的this會指向外層函式的this,
所以在vue要使用this的話,建議使用 一般函式 寫法。
此時箭頭函式裡的this會指向外層函式的this,
所以在vue要使用this的話,建議使用 一般函式 寫法。
bind/apply/call 的 this
一般函式使用 bind/apply/call 時,
this
就是所傳入的物件箭頭函式使用 bind/apply/call 時,
this
不會有變化,規則一樣是 依據外層函式(function)裡的this 是什麼就跟著是什麼。
範例1
1 | <button id='btn'>btn</button> |
1 | function add(x, y){ |
範例2
1 | <button id='btn'>btn</button> |
1 | const add = (x, y) => { |