【JS檔案揭秘】第四集 關於this的討論到此為止
- 2019 年 10 月 3 日
- 筆記
網上關於this的指向問題的部落格文章很多,但大多數都是複製粘貼,也不能用簡潔的語言講清楚,而是不停地寫一些示例,看得人云里霧裡。
其實關於this的指向並不難,只是沒有人去做一個好的總結和試驗,導致這個問題莫名其妙被複雜化了。
這一集,我只給出結論,以及判定的通用方法,至於是否確實如我所講,大家可以自行驗證。
畫圖理解
假設我們現在有一個函數foo,要判斷其中this的指向,可以根據下圖來分析:

第一步,判斷函數是什麼類型:箭頭函數、普通函數還是綁定類函數(bind、call、apply);
對於箭頭函數,需注意,首先箭頭函數其實是沒有 this 的,箭頭函數中的 this 只取決包裹箭頭函數的第一個普通函數的 this。如果往上級找一直沒找到包裹它的普通函數,那麼該箭頭函數中的this指向全局對象。在瀏覽器中,全局對象當然就是window;
而對於綁定函數來說,this指向我們自定義的參數,在bind/call/apply中,即是第一個參數,第一個參數在瀏覽器環境中的預設值為window。這種情況屬於人為地改變this指向,順帶一提:如果對一個函數進行多次bind,只有第一次的bind是生效的,這屬於一個語法知識。
第二步,對於普通函數來說,又分兩種情況:是被當作構造函數調用,還是被當作普通函數調用。
如果是通過new關鍵字對其進行實例化,也就是把這個函數當作構造函數使用,那麼this恆指向實例化後的對象,此時的this是一個地址指針,指向實例化過程中在堆記憶體新開闢的用於存儲實例化對象的那一塊空間;
如果是當作普通函數調用,那麼誰調用它,this就指向誰。有一種情況是類似於foo()這樣的調用,在瀏覽器中其實這相當於window.foo()。所以調用者為全局對象window,this便指向window。

當然,有時候會出現混合調用的情況,這時候就需要根據優先順序來決定,優先順序排名如下:
構造函數(new)> 綁定函數(call/apply/bind)> 具體對象調用(obj.foo())> 全局對象調用(foo())
