??? 最近在閱讀《
JavaScript
高級(jí)程序設(shè)計(jì)》,未免遺忘讀過(guò)的內(nèi)容,就打算以博客的形式做些讀書(shū)筆記。今天介紹的是
JavaScript
中的四種定義對(duì)象的方法,除了這四種方法,還有工廠方法來(lái)定義對(duì)象,但考慮到其簡(jiǎn)單性及非正規(guī)性,這里就不做介紹。和
Java
這樣的面向?qū)ο笳Z(yǔ)言相比,
JavaScript
更像是函數(shù)式語(yǔ)言,其并沒(méi)有類(lèi)的概念,蓋之以對(duì)象定義的概念,而具體創(chuàng)建的對(duì)象叫做對(duì)象的實(shí)例。
??? 1)構(gòu)造函數(shù)方式定義對(duì)象。
這種方式是在構(gòu)造函數(shù)內(nèi)定義屬性和方法。這里舉個(gè)簡(jiǎn)單的例子:
??? function?Animal(name){
????????this.name?=?name;
????????this.introduceSelf?=?function(){
????????????window.alert("I?am?a?"?+?this.name+"!");
????????};
}
??? 對(duì)象的實(shí)例化如下:
var?dog?=?new?Animal("dog");
dog.?introduceSelf();
??? 當(dāng)然,
也可以將對(duì)象的方法在構(gòu)造函數(shù)外定義,如下所示:
function?introduceSelf(){
????window.alert("I?am?a?"?+?this.name+"!");
}
????function?Animal(name){
????this.name?=?name;
????this.introduceSelf?=?introduceSelf();
}
??
這種在構(gòu)造函數(shù)內(nèi)定義所有的屬性和方法的方式,使得構(gòu)造函數(shù)相當(dāng)于
Java
中類(lèi)的概念。而將方法的具體定義獨(dú)立地放在構(gòu)造函數(shù)外,會(huì)使得對(duì)象的定義和方法的定義并不緊密,如果在一個(gè)文件中這樣的方法和對(duì)象定義多的話,就會(huì)看起來(lái)凌亂許多。
??? 2)
原型方式。
該方式利用對(duì)象的
prototype
屬性,可以將其看成創(chuàng)建新對(duì)象所依賴的原型(關(guān)于
prototype
的詳細(xì)信息,可以百度一下,這方面的資料還是很多的)。這種方式將構(gòu)造函數(shù)做成空構(gòu)造函數(shù),然后將所有的屬性和方法被直接賦予
prototype
屬性,還是前面的例子,重寫(xiě)如下:
??? function?Animal(){
????
}
Animal.prototype.name?=?"animal";
Animal.prototype.introduceSelf?=?function(){
????window.alert("I?am?a?"?+?this.name+"!");
};
//對(duì)象的實(shí)例如下:
var?dog?=?new?Animal();
dog.name?=?"dog";
dog.introductSelf();
??
這種方式的缺點(diǎn)是顯而易見(jiàn)的,就是不能在構(gòu)造函數(shù)中對(duì)屬性進(jìn)行賦值操作。還有一點(diǎn)是,對(duì)于引用類(lèi)型的屬性(如
Array
實(shí)例),實(shí)例化的多個(gè)對(duì)象將共享一個(gè)引用。正因?yàn)檫@么多的問(wèn)題,這種對(duì)象定義的方式并不可取。
??? 3)
構(gòu)造函數(shù)、原型混合方式。
這種方式是最為流行的對(duì)象定義方式。它結(jié)合了構(gòu)造函數(shù)及原型方式。這種方式用構(gòu)造函數(shù)定義對(duì)象的所有非函數(shù)屬性,用原型方式定義對(duì)象的函數(shù)屬性(方法)。重寫(xiě)前面的例子:
function?Animal(name){
????this.name?=?name;
}
Animal.prototype.introduceSelf?=?function(){
????window.alert("I?am?a?"?+?this.name+"!");
};
???
??? 4)
動(dòng)態(tài)原型方式。
和構(gòu)造函數(shù)、原型混合方式相比,動(dòng)態(tài)原型方式只是在函數(shù)屬性定義的位置上有所不同。重寫(xiě)前面的例子:
???
function
?Animal(name){
????
this
.name?
=
?name;
????
if
(
typeof
?Animal._initialized?
==
?'undefined'){
????????Animal.prototype.introduceSelf?
=
?
function
(){
????????????window.alert(
"
I?am?a?
"
?
+
?
this
.name
+
"
!
"
);
????????};
????????Animal._initialized?
=
?
true
;
????}
}
? ??? 其中_initialized是Animal的全局私有屬性(JavaScript中沒(méi)有私有屬性的概念,所有的屬性都是共有的,但為了表明一些屬性的私有特性,人們習(xí)慣在屬性名前加上“_”。),當(dāng)?shù)谝淮螌?shí)例化Animal時(shí),if條件就為真,這樣就會(huì)定義Animal中的函數(shù)屬性。由于“Animal._initialized = true;”的存在,函數(shù)的定義調(diào)用一次而無(wú)論實(shí)例化多少個(gè)對(duì)象。