js函數中的this關鍵字


關於這個this關鍵字,也是很多項目中常常被用到的,那么,有人也許會問,干嘛要用this呢,在函數被調用時,直接指明是什么對象在調用不就行了?還整那么個模模糊糊的概念出來干嘛?不過嘛,存在即真理,既然有這么個東西,那也就有他存在的意義,下面來看看吧。

 

首先,我們要先回憶一下js函數都有哪幾種調用的場合,有如下幾種場合:

1、很常規的調用(即直接調用,其實你發現也是全局調用);

2、作為某個對象的豆哥方法被調用;

3、作為構造函數,用來新建某個新對象(object);

4、很讓人頭大的apply調用(在實現部分繼承的時候經常這么干)。

 

好了,一起來看看上述幾種情況下this關鍵字是怎樣被玩的出神入化的。

一、純粹的函數調用

這是函數的最通常用法,屬於全局性調用,因此this就代表全局對象Global,那么這里Global很多人又很迷惑了,實則在瀏覽器環境下,Global也即是window對象,global對象是單體內置對象,即不依賴宿主環境的對象,而window對象依賴瀏覽器。

看下面這段代碼:

function test(){

  this.name = "dearxiangxiao";

  console.log(this.name );

}

test();  //dearxiangxiao

感覺還是很神奇的,不知不覺test函數里面定義的屬性,在外面也可以讀取了?對代碼做一些修改,如下:

var name = "xiangxiao";

function test(){

  this.name  = "dearxiangxiao";

}

test();

alert(name); //  dearxiangxiao

可以看出,在執行完test函數之后,name的值被改變了,原因何在?這里就是這個調用test的對象是Global在作怪,既然test是被全局對象Global調用的,那么this也就指向Global對象了,全局對象的屬性,當然可以讀取並修改了,沒啥錯。

 

二、作為對象方法的調用

函數還可以作為某個對象的方法調用,這時this就指這個上級對象,也來看一段代碼:

function test(){

  console.log("my name is "+this.name + " and my profession is "+this.profession);

};

var person = {};

person .name= "dearxiangxiao";

person.profession = "projector";

person.interduce= test;

person .interduce(); // my name is dearxiangxiao,and my profession is projector

這里很好理解,既然是person在調用test函數,那么理所應當的this指向的是person實體,也就是前面說的調用函數的上一級對象,它的name和profession 屬性當然應該被讀取出來了。

 

三、作為構造函數調用

所謂構造函數,就是通過這個函數生成一個新對象(object)。這時,this就指這個新對象,也來看一段代碼,將一中的例子做輕微的修改:

var name = "xiangxiao";

function Person(){

  this.name  = "dearxiangxiao";

}

var person1 = new Person();

console.log(name); // xiangxiao

console.log(person1.name);   //  dearxiangxiao

可以看出,this指向的對象是剛剛新建的person1,讀取出了它的名稱dearxiangxiao,而直接打印name變量,值仍然未變,為之前的xiangxiao。這更加表明this指向person1,而不是Global對象。

 

四、apply調用

apply()是函數對象的一個方法,它的作用是改變函數的調用對象(實則是將某某對象的某個方法放到另一個好基友對象那里去執行),它的第一個參數就表示改變后的調用這個函數的對象。因此,this指的就是這第一個參數。

關於這個apply,可能大多數人不太喜歡用它,要想調用某個對象直接調用不就好了么?但是應該想到,假如你想調用別人寫好的某個方法,某些參數變量卻要用到你自己的,怎么辦?apply和call就派上用場了,這也是js面向對象思維轉換的重要一環,必須理解的(關於apply和call具體詳情,請看我的另一篇博文:js面向對象思維轉換的一個階梯:apply和call)。

 

下面還是來看個例子吧,這里把三中的例子做一些輕微的修改:

var name = "xiangxiao";

function test(){

  console.log(this.name);

}

var person1 = new Person();

person1.name = "dearxiangxiao";

person1.interduce = test;

person1.interduce.apply();  // 這里輸出的四xiangxiao

怎么回事,不是說好了的要改變函數的調用對象么?怎么還是被Global調用了?不急不急,來看看apply后面的括號里,沒任何東西,默認沒有殘數時是全局對象Global,因此,此處也就真的是調用出了Global的name變量。那person1.interduce.apply()怎么理解呢?可以這么理解:將person1實體的interduce方法放到Global對象上去執行。

好了,我們剛剛在前面說了,apply后面括號里的第一個參數,即為this的指向,那么改一改上面的最后一句代碼吧,如下:

person1.interduce.apply(person1); // 這里輸出的就是dearxiangxiao

 

得到person1的name屬性值了,突然冒出個想法,這里person1.interduce.apply(person1) 理解出來貌似很拗口額:將person1實體對象的interduce方法放到person1實體對象上去執行,什么鬼?自己的方法自己直接調用不好么?寫成 person1.interduce()就行了噻!!!當然可以,那樣更簡潔,不過,這就是apply方法的特點所致吧,自己的方法,轉一圈回到自己手里被調用了,還給出個冠冕堂皇的解釋,哈哈,就不吐槽了,我們還是要看到apply帶給我們的諸多好處的。

這篇博文就是這么多內容了,希望大家會喜歡。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM