1. 程式人生 > 其它 >JavaScript:this指標

JavaScript:this指標

this指標,儲存的是一個記憶體地址,如同變數一樣,指向一塊記憶體區域;

而這個記憶體區域,儲存的就是一個物件的資料,那麼這個物件是什麼呢?

通常來說,this指標,主要是用在方法(函式)中,用來指向呼叫方法(函式)的物件;

比如說,有個方法eat(),這個方法裡面有個this指標;

Tom呼叫eat時,this指標指向的就是"Tom";

Jerry呼叫eat時,this指標指向的就是"Jerry";

也就是說,this指標,總是指向直接呼叫者。

好,現在我們來看一下,兩個不同於上面所述規則的特殊情況:

  • ”沒有“呼叫者

    看下面程式碼:

    我們知道,如果是使用var宣告的變數,實際上是成為了window

    物件的方法,那麼aaa()實際上就是window.aaa(),也就是省略了window的寫法,那麼,this指向的就是window物件,我們可以理解;

    但是,上面我們使用let宣告的變數,為什麼this指向的還是window物件呢?

    要知道,let宣告的函式,並不是window物件的方法,window物件也無法呼叫,那麼此時aaa()是由誰呼叫的呢?我們現在無法得知,但是可以肯定的是,絕對不是window物件;

    再來看函式aab(),雖然它是function宣告的函式,但是因為它是在程式碼塊中宣告的,所以它也不是window物件的方法,那麼aab()又是被誰呼叫的呢?為什麼它的this指標,也指向window

    物件呢?

    事實上,這是歷史遺留問題,如果我們開啟了嚴格模式,此時兩個this將都會是undefined,這是符合邏輯的,既然“沒有”呼叫者,那麼this就沒有指向,當然就是undefined

    如下所示,就印證了我們前面所說的:

  • 箭頭函式沒有this指標

    首先說明,箭頭函式,確實沒有自己的this指標;

    也就是說,箭頭函式裡面的this,並不能指向呼叫箭頭函式的物件;

    那麼,此時this,指向的是誰呢?

    看下面程式碼:

    我們將上圖與上上圖進行比較,仔細觀察一下輸出結果的不同;

    在嚴格模式下,上圖三個this指向的都是window物件,與上上圖完全不一樣,這至少說明,箭頭函式的this,和function

    宣告的函式的this,有不同的表現;

    再看下面這個程式碼:

    上圖與上上圖的區別,就是在最後一行程式碼,我們將obj1作為obj2的一個物件,從而再多一次呼叫arrow()方法,結果依然還是指向window物件,似乎無論增加多少次中間呼叫者,最終都會指向window物件,說明箭頭函式的this,並不是在指向呼叫箭頭函式的物件;

    現在我們嘗試,將箭頭函式arrow的可見性,降低一些,看下面的程式碼:

    上圖將箭頭函式內arrow的可見性,控制在了用關鍵字function宣告的函式外arrow內部,這樣,要使用箭頭函式,就得呼叫外arrow

    對於arrow(),上面我們已經討論過,此時外arrow函式“沒有”呼叫者,所以this是undefined

    對於obj1.arrow(),此時this指向,呼叫外arrow函式的obj1;

    對於obj2.arrow(),此時this指向,呼叫外arrow函式的obj2;

    對於obj2.obj1.arrow(),此時this指向,呼叫外arrow函式的obj1,注意,此時obj2呼叫obj1,而obj1呼叫外arrow函式,所以this指向obj1;

    可以看到,this的表現,完全就是外arrow函式的this指標的表現;

    也就是說,此時,箭頭函式的this,其實並不屬於箭頭函式,而是屬於包圍箭頭函式的外部程式碼塊,在這裡也就是指外arrow函式;

    所以,在考慮箭頭函式的this指標的指向的時候,我們完全可以把箭頭函式當成一般的執行語句,而不是一個函式,這也是為什麼說箭頭函式沒有this指標的緣故;

    現在回過頭看上上圖,我們就能理解,此時箭頭函式是直接在script標籤中的,作為一個普通的執行語句,它的外層只剩下瀏覽器視窗,也就是window物件了,所以這些this指標才全部指向window物件;

總結:

  • this指標,總是指向它所在函式體的直接呼叫者;
  • 直接函式名()這樣“沒有”呼叫者的函式呼叫,在嚴格模式下,this為undefined;在普通模式下,this指向window物件;
  • 箭頭函式沒有this指標,此時將箭頭函式當做一般語句,this指標屬於箭頭函式所在的函式體的直接呼叫者;而且注意,如果箭頭函式是全域性作用域的話,無論什麼模式,this總是指向window物件;