JavaScript 核心觀念(41)-函式以及 This 的運作-this:簡易呼叫
前言
這一篇將會接續前一章節沒有說明的「簡易呼叫」,也就是 Simple Call。
Simple Call
首先什麼是 Simple Call 呢?Simple Call 中文是簡易呼叫,基本上直接呼叫一個函式內的 this
就會形成簡易呼叫
1 | function fn() { |
而簡易呼叫的特色是什麼呢?通常簡易呼叫會導致 this
直接指向 Window
,因此上方範例就是直接指向 Window
,若將程式碼改成以下就可以看出來差異
1 | function fn() { |
但是在實際開發時,請盡可能避免使用到 Simple Call 的 this
,而 Simple Call 會發生在哪幾種狀況呢?簡單來講只要你看函式是直接執行的,並且裡面有使用到 this
那麼就會形成 Simple Call,因此這邊可以看一段課程範例
1 | var myName = 'Ray'; |
在此可以看到上方範例不管怎麼樣都是指向 window
,而 IIFE 都會產生 Simple Call 了,那麼閉包呢?
1 | function fn() { |
上方範例我們依然可以看到 this
是指向 window
更不用說因為 this
指向 window
的關係,而底下並沒有 a
這個變數而出現 undefined
,而在此也是因為「直接呼叫該函式」而導致產生 Simple Call,因此若將來看到直接呼叫
函式的方式,那麼就必定會產生 Simple Call。
除此之外還有一種狀況會形成 Simple Call,也就是 Callback 的形式,例如
1 | function fn(cb) { |
這種狀況也產生 Simple Call,基本上必須看它是如何執行的,如果是直接執行的話,那麼必定會產生 Simple Call 導致 this
跑掉,但是如果將程式碼改成以下,那麼結果就會不同
1 | function fn(cb) { |
因為上方的呼叫方式就變成了在物件下呼叫,因此 this
就不會指向到 window
,但通常 Callback 都會形成 Simple Call 尤其是 JavaScript 本身內建的方法都常都會形成這個問題,例如先前的範例就是一個狀況
1 | var myName = 'JavaScript' |
除此之外 ES6 的 forEach 也是一個 Callback
1 | var arr = [1, 2, 3]; |
因此這邊基本上只要看到傳入的是一個函式又傳入另一個函式,基本上就有很高的機會變成 Callback 而形成 Simple Call。
最後拉回剛剛的一個範例
1 | var myName = 'JavaScript' |
上面範例我們知道 this
會跑掉,那麼如果想避免 this
跑掉的話,該怎麼做呢?基本上常見的做法就是在 CallBack 外層宣告一個變數儲存 this
,通常名稱會是 vm
或是 self
1 | var myName = 'JavaScript' |
而上方寫法基本上與下方相同只是程式碼撰寫方式放的方式不同而已
1 | var myName = 'JavaScript' |
但通常來講其實我不太建議將變數命名為 self
,因為 self
其實就是 window
本身,在此可以看這邊的討論串,以下擷取重點
You should avoid self as there is a window.self object and you could end up using that accidentally if you forget to declare your own self var (e.g. when moving some code around). This can be annoying to spot/debug. Better to use something like _this。