(三)個人JavaScript系列:不一樣調用方式的this指向

人生自是有情癡,此恨不關風與月javascript

今天所寫的內容,是對以前的內容的總結和擴展。老實說,對於本身以前的一些杜撰和臆測,我並非很滿意。因此這篇博文,我但願能來點乾貨。java

不一樣調用方式的this指向

在JavaScript中,咱們能夠用this來指代當前的對象。這種感受就像使用Java同樣。不過與Java不一樣的是,在Java中,this的指代老是很明顯的;然而在JavaScript中,this的指代在不一樣的調用方式下,其指代每每不一樣。我爲此分爲四類:數組

1. 做爲函數調用,指代的是全局對象

若是咱們定義如下函數:app

function f() {
    console.log(this);
}

而後將其做爲普通對象調用,即f(),此時this指代的是全局對象window。函數

2. 做爲對象的方法調用,指代是調用對象自己

若是咱們將f做爲一個對象的方法,也就是說做以下改造:this

var a = {};
a.f = f;

而後經過對象a調用方法f,即a.f(),此時this指代的就是調用者a。prototype

3. 做爲構造器函數使用,指代的隱含的新建對象

若是咱們用new語句調用函數f,即new f(), 則此時this指代的是新建的對象。code

4. call和apply的方式

除了上述幾種方式外,咱們還能夠任意指定this的指代,這就是call和apply發揮做用的地方了。call和apply是每一個函數對象都擁有的方法,其第一個參數就是要指定的this值,後面是函數正常的參數值。其細微的差異在於參見下面的示例:對象

function g(name, age) {
    this.name = name;
    this.age = age
}

var a = {};

g.call(a, 'xiaoming', 18);
g.apply(a, ['xiaoming', 18]);

即call的非this參數只需在後面列出就能夠了,apply要把它們封裝到一個數組裏面去。ip

從某種程度上說,前面的三種函數調用形式都是call方式的一種語法糖:

  1. f() === f.call(window)
  2. a.f() === f.call(a)
  3. new f() === var _a = {}; f.call(_a)

call有很強大的能力,咱們經常使用的函數借用就是利用call能夠動態指定this這一特性的。例如Array.prototype.slice.call(a)能夠將看起來像數組的對象a轉化爲實際的數組對象。

var a={length:2,0:'first',1:'second'};
Array.prototype.slice.call(a);//  ["first", "second"]
 
var a={length:2};
Array.prototype.slice.call(a);//  [undefined, undefined]
相關文章
相關標籤/搜索