this是指向誰
在撰寫前端的專案的時候,時常會遇到 this 指向誰的問題。
所以這邊,就用將書中和網路上的文章讀到的內容,整理並記錄下來。
this什麼時候被決定
在我自己寫的上一篇有提到作用域的部分。
在JavaScript中的function的作用域是靜態作用域,也就是代表在function定義的當下,就被定義了。
而Javascript中的this,就是動態的,這代表什麼,就是function被呼叫的當下,相對應的this才被定義。
在大部分的情況下,this代表的就是呼叫function的物件。
來個範例
1 | const getGender = function() { |
上面這個範例,就可以很好的體現什麼叫做,this代表呼叫的function的物件這個概念。
this 不等於 function本身
在JavaScript中的function本身就是一個物件型別,雖然,它的typeof的結果是function,但它的本質是物件。
如果,我們為一個function新增一個屬性,那此時,在該function中的this所呈現的成員屬性會不會就是我們為該函式新增的成員屬性的值呢?
馬上來個範例
1 | var func = function() { |
答案是什麼呢??
答案是0。 當初我在書上看到這個答案的時候,我也是蠻崩潰的XDD
那我按照書中給的脈絡,來解析一下這一題為什麼是這種結果。
首先,先記得this代表呼叫function的物件 的概念。
第二,我們呼叫func()的時候,並沒有特意用其他物件來呼叫它。
那這時的this就代表window,為什麼呢? 因為,變數func是一個全域變數,它是屬於window物件的成員屬性,
所以,當我們直接呼叫foo()時,其實就等同於我們直接用window來呼叫foo(),跟foo函式本身根本無關。
代表func.a 根本沒有被更改過,所以,就維持原本的0囉。
實際上被更改的a是window的a,而window的a原本是undefined,故在經過計算之後,window.a會變成NaN。
巢狀function裡面的this
在這邊的情境最主要是用到以下兩個概念
- JavaScript中,變數最小有效範圍是function
- this代表呼叫該function的物件
直接來的範例
1 | var obj = { |
最終的console.log的結果是10 和 undefined。
首先,我們會先用到this代表呼叫該function的物件這個概念
我們利用obj來呼叫hello函式,所以,在hello內部第一層的this代表的就是obj這個物件,而obj的物件的a成員屬性值就是10囉。
第二,我們會用到JavaScript中,變數最小有效範圍是function這個概念
所以,在test函式是一個獨立的區域,它裡面的this和外部的this是不一樣的。 那如果,我們沒有特別對this定義的話,它的預設值
就是window,而window本身並沒有定義a成員屬性,所以,結果會是undefined。
監聽事件裡面再增加其他函式
今天如果我們在addEventListener裡面,再加入一些ajax的callback function或一些其他的function。
那因為js的變數最小有效範圍的概念,會導致內層的函式的this跟外層的this是不一樣的。
此時,我們就可以在外層利用一個變數來儲存外層環境的this,再將這個變數丟到內層的函式中,
就可以在內層的函式使用外層的this囉。
1 | ---JavaScript--- |
使用.call輔助到底this是誰
雖然這邊我還沒有紀錄.call這個功能在幹嘛,而且要怎麼用,但是,在這邊先不要在意它XDD
你就記得我們可以透過.call來呼叫function,並在呼叫的當下同時傳入this的指定對象。
在Huli的這篇文章中有特別介紹這篇文章中所介紹的利用call來輔助this是誰。
那這個小撇步地轉換規則就是你在呼叫 function 以前是什麼東西,你就把它放到後面去。
來個範例吧
1 | const obj = { |
我們用.call來傳換一下上面的範例
1 | const obj = { |
如此,應該就很清楚為什麼最終的結果分別是1 和 undefined了吧~~
在test被呼叫的時候,因為,並沒有特別被哪個物件所呼叫,所以,call裡面就直接放入undefined,而在非嚴謹模式下,
this就會是預設值window囉。
強制指定this的方式
bind, call, apply
舉個bind、call 和 apply用法
1 | function func(argv0, argv1) { |
以上可以看到,這三種方式的使用方法。我們可以直接指定我們想要的this對象是誰。
箭頭函式
箭頭函式的this決定的方式是在定義箭頭函式環境的this,該箭頭函式的this就是誰。
舉的範例
1 | const obj = { |
結果會是10和10。
因為,箭頭函式func在定義的環境的this是obj,所以,在這個箭頭函式內部的this就是obj。
所以,this.a的結果是10。
參考文章
- 008天重新認識JavaScript-kuro
- https://blog.huli.tw/2019/02/23/javascript-what-is-this/
- https://zhuanlan.zhihu.com/p/23804247