讀古今文學網 > 編寫高質量代碼:改善JavaScript程序的188個建議 > 建議87:分辨this和function調用關係 >

建議87:分辨this和function調用關係

JavaScript的this一直是容易讓人誤用的關鍵詞,尤其對於熟悉Java的程序員來說,因為JavaScript中的this與Java中的this是有很大不同的。在一個function的執行過程中,如果在變量的前面加上了this作為前綴,如this.myVal,對此變量的求值就從this所表示的對象開始。

this的值取決於function被調用的方式,一共有5種:

❑如果一個function是一個對象的屬性,那麼在funtion被調用時,this的值是這個對象。

❑如果function調用的表達式包含句點(.)或,那麼this的值是句點(.)或之前的對象。如在myObj.func和myObj["func"]中,func被調用時的this是myObj。

❑如果一個function不是作為一個對象的屬性,那麼在function被調用時,this的值是全局對象。當一個function中包含內部function時,不理解this的正確含義就很容易造成錯誤,因為內部function的this值與它外部的function的this值是不一樣的。


var myObj={

myVal:"Hello World",

func:function{

alert(typeof this.myVal);//string

var self=this;

function inner{

alert(typeof this.myVal);//undefined

alert(typeof self.myVal);//string

}

inner;

}

};

myObj.func;


在myObj函數體內有個內部名為inner的函數,在inner被調用時,this的值是全局對象,因此找不到名為myVal的變量。這時通常的解決辦法是將外部function的this值保存在一個變量中(此處為self),在內部函數中使用它來查找變量。

❑如果在一個function之前使用new,則會創建一個新的對象,該funtion也會被調用,而this的值是新創建的那個對象。


function User(name){

this.name=name

};

var user1=new User("Alex");


調用new User("Alex")會創建一個新的對象,以user1來引用,User這個function也會被調用,會在user1這個對象中設置名為name的屬性,其值是Alex。

❑如果通過function的apply和call方法來指定它被調用時的this的值,那麼apply和call的第一個參數都是要指定的this值,兩者不同的是調用的實際參數在apply中是以數組的形式作為第二個參數傳入的,而在call中除了第一個參數外其他參數都是調用的實際參數。

JavaScript中並沒有Java或C++中的類的概念,而是採用構造器的方式來創建對象。在new表達式中使用構造器就可以創建新的對象。由構造器創建出來的對象有一個隱含的引用指向該構造器的prototype。

所有的構造器都是對象,但並不是所有的對象都能成為構造器。能作為構造器的對象必須實現隱含的Construct方法。如果new操作符後面的對象並不是構造器,會拋出TypeError異常。

new操作符會影響function調用中return語句的行為。當調用function時有new作為前綴,如果返回的結果不是一個對象,那麼新創建的對象將會被返回。


function user(name){

this.name=name;

}

function anotherUser(name){

this.name=name;

return{

"badName":name

};

}

var u1=new User("Alex");

alert(typeof u1.name);//string

var u2=new anotherUser("Alex");

alert(typeof u2.name);//undefined

alert(typeof u2.badName);//string


在上面代碼中,函數anotherUser通過return語句返回了一個對象,因此u2引用的是返回的那個對象;而函數user並沒有使用return語句,因此u1引用的是新創建的User對象。