整理這些技術筆記真的很花時間,如果你願意 關閉 Adblock 支持我,我會把這份感謝轉換成更多「踩坑轉避坑」的內容給你!ヽ(・∀・)ノ
關於this是一個很神奇的東西這件事情
前言
我學習 JavaScript 中令我感到最痛苦最煩惱的其中一個東西就是 this,所以這邊就針對 this 來做一下紀錄學習。
this是什麼?
this 是 JavaScript 函式內的一個關鍵字,在不同的時機點使用就有可能有不同的結果,對於學習 JavaScript 的人來講實在非常頭痛。
全域(Global)
範例1
1 | |
這時候我們可以看到 this 會去尋找 Window 下叫 name 的東西,所以 console.log(this.name); 就會顯示小明。
所以我們這邊大膽測試一下,看一下現在的 this 是什麼。
1 | |

可以發現此時的 this 代表 window。
所以可以將console.log(this.name);這樣看

因為目前的 this 所代表的就是 window,所以 this 會從全域中去找 name 才會找出小明這個答案。
範例2
function 下使用 this,那麼會影響 this 嗎?
1 | |
從結果來看跟範例1是沒有什麼差別,console 一樣顯示小明。
如果用圖解來看的話會更清楚,namefu(); 其實是這樣的

範例3
另外 this 在一種特別狀況下會出現 undefined。
1 | |

這是一個很奇妙的狀況,嚴格模式下 this 是會變成 undefined 的,而在 ES5 的說法是…
若在非嚴格模式下
this會指向全域 (window),但在嚴格模式就會因為安全上的考量而禁止this指向全域,簡單來講 this 只要一指向全域 (window) 就會變成undefined。
那麼如果我們將 name 拉入 function 中會怎麼樣呢?
1 | |

結果也是一樣會是 undefined,用圖片來看就會很清楚為什麼。

所以嚴格模式 ("use strict") 下,只要 this 指向是 window 那麼絕對就會是 undefined。
那麼該如何解決嚴格模式下 undefined 問題
1 | |

此時可以看到 this 出現的是小王,所以可以理解成 this > a 底下去找有沒有 name。
從前面總總結論來看 this 會依照執行的環境來找值,用圖片來說明就是這樣子。

this 往前一個去找 name 的屬性,而 this 前面就是 a,所以才會出現小王。
物件(Object)
範例 1
1 | |
結果可以發現 console 可以取得小明。
範例 2
那如果變成這樣呢?
1 | |
此時會出現 undefinde,這邊一樣更圖片來表達更清楚。

因為 this 會去找 obj 中的 name,但 obj 中並沒有 name 這個屬性,所以就回傳了 undefined
但是如果是這樣寫呢?
1 | |
這時候就會抓到小王,而不是取得小明,跟上面圖片是一樣的。

所以由此可知 this 的特性是往前一層找 name,而 obj 中現在有 name 屬性,故輸出小王而不是小明。

但是下面這個範例就不太一樣了。
1 | |
首先在還沒執行 obj.x; 就直接將 obj.x; 賦予 a,然後再執行 a(),這時候會跑出小王,但是如果我們依照剛剛前面的想法來講用圖解這樣子是沒錯的。

那為什麼 name 會是小王呢? x 裡面有一個 name 重新賦值所導致。

範例 3
如果改寫這樣子呢?
1 | |

結果一樣會是小王,因為你先執行了 x() 這個方法,所以 this 是跑完找完東西在賦予值進去a
但是有一種狀況下滿特別的,他會變成小明
1 | |

這時候奇妙的小明就出現了。
那麼為什麼會導致這樣子呢?這是因為 obj.x,在還沒執行下就直接賦予給 a,所以變成了 a 是一個方法,就是物件傳參考觀念是一樣的,所以用圖解來看 a 就會變成這樣。

範例4
有時候物件裡面會寫得很複雜,所以如果這樣子寫呢。
1 | |

就剛剛的結論來講 this 會去向上級找 name,所以 this 從 x 找到的 name 就是小虎。

可是如果依照剛剛的重新賦值並不優先執行呢?
1 | |

就剛剛得到的結論來講,因為直接將 function 賦予至 a,所以實際上 a 的上級就是 window

結論
this 的使用時機真的很奇妙,會依照使用的環境來取得不同資料,基本上可以得到幾個結論心得。
1.this 特性是向上找
2.如果執行 function 的時候是在全域下執行,那麼就對得到全域的答案,反之若是在區域下執行就會得到區域的答案。
3.嚴格模式下的 this 若指向 window 就絕對會出現 undefined。
補充
前陣子在撰寫 jQuery 的時候發生一件事情,透過 this 去獲取 data-id,但卻會出現 undefined。
1 | |
查看了一下 this 才發現,this 指向到window了,並不是指向 .deletePost,所以才會找不到 data-id。

後來經過大大提醒 this 在甚麼樣的情況下會改變,然後提供了一篇文章給我參考,裡面講到了一句話。
Arrow function 對於它也是又愛又恨的,看似簡約的外型卻有著全新的體驗,它有著更簡短的語法以及重新定義的 this。
看到這段大概知道問題了,在箭頭函式下 this 對應呼叫方式被重新定義,所以才會導致無法抓到 data-id。
所以重點整理一下
- 綁定的 this 不同之處
- 傳統函式: 依呼叫的方法而定
- 箭頭函式: 依綁定到其定義時所在的物件 <-這句話真的有看沒有懂。
為了搞懂這個觀念,所以拿前面的練習來試試看
1 | |
用原本的 function 來執行 this.name 會跑出小虎無誤。
但如果改成箭頭函式呢?
1 | |
神奇的事情發生了,小明出現!

所以由此可知在箭頭函式,原本的觀念就會被重新定義…不在是這樣子

附帶一題這個就是傳統函式:依呼叫的方法而定
所以若再箭頭函式下使用 this 就會被重新定義至window。

所以就會變成這樣

如果要確定 this 指定在 function 中就必須這樣撰寫。
1 | |
簡單來說若要使用箭頭函式的 this,外層就要使用 function 來避免 this 指向至 window,這樣 this 才會正確指向進 function 屬性中。
所以依照這個觀念將箭頭函式改寫成 function 來查看 this 現在指向哪裡囉。
1 | |
所以就可以看到 this 正常的指向我要的 dataset 了QQ

參考
整理這些技術筆記真的很花時間,如果你願意 關閉 Adblock 支持我,我會把這份感謝轉換成更多「踩坑轉避坑」的內容給你!ヽ(・∀・)ノ