1. 程式人生 > >深入淺出JavaScript之this

深入淺出JavaScript之this

深入淺出JavaScript之this

JavaScript中的this比較靈活,根據在不同環境下,或者同一個函式在不同方式呼叫下,this都有可能是不同的。但是有一個總的原則,那就是this指的是,呼叫函式的那個物件。

全域性的this(瀏覽器)

全域性作用域的this一般指向全域性物件,在瀏覽器中這物件就是window,在node中這物件就是global。

一般函式的this(瀏覽器)

一般的函式宣告或者函式表示式,直接呼叫函式的話,this依然指向全域性物件,在瀏覽器中這物件就是window,在node中這物件就是global。


再舉一個例子,看完就非常透徹了

 
為了證明this就是全域性物件,對程式碼做一些改變:

 
執行結果還是1。再變一下:


但是在嚴格模式下,一般函式呼叫的時候this指向undefined,這也是node為什麼要用嚴格模式的一個原因。

作為物件方法的函式的this

this作為物件方法來使用是比較常見的。

下面這個例子,我們建立了一個物件字面量w,w裡面有個屬性ff,它的值是一個函式物件,把函式作為物件屬性的值這種方式我們常常叫作物件的方法。作為物件的方法呼叫的時候,這時候this指向物件w


我們不一定要定義成函式字面量這樣子的物件,像下面這種情況,我們只定義了一個物件s,如果直接呼叫independent()函式的話,this會指向window,但是我們通過賦值的方式,臨時建立一個屬性ff,並指向函式物件的時候,我們仍然拿到了11。

所以並不是看函式是怎麼建立的,而是隻要將函式作為物件的方法去呼叫,this就會指向這個物件。

物件原型鏈上的this

下面這個例子中:我們先建立了一個物件a,裡面有一個屬性ff,函式作為物件屬性的值,我們通過Object.create(o)建立了一個物件p,p是一個空物件,它的原型會指向a,然後使用p.a = 1; p.b = 4建立物件p上的屬性,那麼我們呼叫原型上的方法時,this.a,this.b依然能取到物件p上的a和b。這裡需要注意的是p的原型才是a,我們呼叫p.f(),呼叫的是原型鏈a上的屬性f,原型鏈上的this可以拿到當前的物件p。

get/set方法與

this

get/set方法中的this一般會指向get/set方法所在物件裡面

建構函式中的this

用new把MyClass作為建構函式呼叫的話,this會指向空的物件,並且這個物件的原型會指向MyClass.prototype(可以看這篇文章對原型鏈的總結),但是呼叫的時候做了this.a = 37的賦值,所以最後this會作為返回值(沒寫return語句,或者return的是基本型別的話,會將this作為返回值),第二個例子return語句返回了物件,那麼就會將a = 38作為返回值

call/apply方法與this

除了不同的呼叫方式外,函式物件有些方法能修改函式執行的this,比如call/apply。

call和apply基本上沒差別,只不過call傳參的方式是扁平的,而apply是把一個數組傳進去。如下面這個例子

什麼時候用call和apply呢?比如我們想呼叫Object.prototype.toString,但是我們想指定某個this的時候,那我們就可以就用Object.prototype.toString.call(this)這樣子的方式來呼叫些無法直接呼叫的方法。如下面這個例子:

bind方法與this

bind方法是es5開始提供的,所以ie9+才支援

總結

做專案的時候會發現這些基礎概念有多麼的重要,如果不把它們逐個落實了,真的是一不小心就會掉進坑裡。