在javascript中惋戏,創(chuàng)建對(duì)象的方式有很多種。假設(shè)我們要?jiǎng)?chuàng)建一個(gè)描述人的對(duì)象忽冻,這個(gè)對(duì)象有一個(gè)name屬性和一個(gè)speak方法。針對(duì)這種情況雌团,我們下面會(huì)一一列舉不同的實(shí)現(xiàn)方式燃领。
1.直接創(chuàng)建對(duì)象
var obj = new Object();
obj.name = 'david';
obj.speak = function(){
alert(this.name);
}
2.對(duì)象字面量的方式
var obj = {
name:'david',
speak:function(){
alert(this.name);
}
}
以上兩種是最常見(jiàn)的創(chuàng)建對(duì)象方式,能夠解決大部分的變量創(chuàng)建場(chǎng)景锦援。然而猛蔽,當(dāng)你需要?jiǎng)?chuàng)建多個(gè)相似的對(duì)象,以上方法就顯得比較乏力了灵寺,你需要不斷的寫(xiě)重復(fù)代碼曼库。這時(shí)候,你需要引入一些設(shè)計(jì)模式來(lái)解決這個(gè)問(wèn)題略板。
3.工廠模式
function createPeople(name){
var obj = new Object();
obj.name = name;
obj.speak = function(){
alert(this.name);
}
return obj;
}
createPeople('people1');
createPeople('people2');
createPeople('people3');
...
工廠模式這種動(dòng)態(tài)創(chuàng)建對(duì)象的方式能夠解決大部分的創(chuàng)建多個(gè)對(duì)象場(chǎng)景毁枯。然而上面的工廠模式仍有所不足。
1.創(chuàng)建的對(duì)象之間毫無(wú)關(guān)系叮称。
2.每次創(chuàng)建對(duì)象都動(dòng)態(tài)創(chuàng)建了匿名函數(shù)种玛,占據(jù)了而外的內(nèi)存空間。而實(shí)際上這些方法都可以公用瓤檐。
因而赂韵,我們引入了構(gòu)造函數(shù)。
4.構(gòu)造函數(shù)
什么叫構(gòu)造函數(shù)呢挠蛉?它實(shí)際上就是一個(gè)普通函數(shù)祭示,只是它跟普通函數(shù)有些區(qū)別,比如:
1.我們建議用首字母大寫(xiě)的函數(shù)名在區(qū)別普通函數(shù)碌秸。
2.沒(méi)有return語(yǔ)句。
3.內(nèi)部有this變量悄窃。
4.使用new關(guān)鍵字調(diào)用讥电。
然后,我們用一個(gè)new關(guān)鍵字去創(chuàng)建對(duì)象轧抗。
function People(name){
this.name = name;
this.speak = function(){
alert(this.name);
}
}
var david = new People('david');
david.speak();//david
var jimmy = new People('jimmy');
jimmy.speak();//jimmy
上述例子中恩敌,我們成功創(chuàng)建了一個(gè)david對(duì)象。然而它是怎么實(shí)現(xiàn)創(chuàng)建對(duì)象的呢横媚?實(shí)際上在new一個(gè)構(gòu)造函數(shù)時(shí)纠炮,它做了如下4個(gè)動(dòng)作:
function people(name){
var obj = new Object();//1.動(dòng)態(tài)創(chuàng)建對(duì)象
People.apply(obj,arguments);//2.把this對(duì)象指向新創(chuàng)建的對(duì)象
obj.__proto__ = People.prototype;//3.把對(duì)象的__proto__屬性指向?qū)ο蟮膒rototype
return obj;//4.返回對(duì)象
}
var david = people('david');
var jimmy = people('jimmy');
david.speak();//david
jimmy.speak();//jimmy
通過(guò)構(gòu)造函數(shù)創(chuàng)建的對(duì)象,彼此是有聯(lián)系的灯蝴。每一個(gè)通過(guò)構(gòu)造函數(shù)創(chuàng)建的對(duì)象恢口,都會(huì)有一個(gè)內(nèi)置的constructor屬性,該屬性指向構(gòu)造方法穷躁。
david.constructor === People//true
jimmy.constructor === People//true
并且耕肩,我們可以通過(guò)instanceof 來(lái)識(shí)別對(duì)象。
david instanceof People//true
jimmy instanceof People//true
這樣就解決了對(duì)象的識(shí)別問(wèn)題。然而用構(gòu)造函數(shù)創(chuàng)建變量猿诸,還是沒(méi)有解決重復(fù)創(chuàng)建實(shí)例方法的問(wèn)題婚被,每次創(chuàng)建對(duì)象,仍然會(huì)創(chuàng)建匿名函數(shù)并指向speak梳虽。有沒(méi)有一種方式能夠讓實(shí)例對(duì)象共享方法或者屬性呢址芯?
jimmy.speak===david.speak//false
為了解決實(shí)例的屬性、方法共享問(wèn)題窜觉。javascript引入了原型的概念谷炸。
具體查看我的其中一篇文章。
5.原型
function People(name){
this.name = name;
}
People.prototype.speak = function(){
alert(this.name);
}
var david = new People('david');
var jimmy = new People('jimmy');
david.speak===jimmy.speak;//true
這種方式把需要共享的方法放到原型中竖螃,當(dāng)訪(fǎng)問(wèn)實(shí)例對(duì)象中的屬性或者函數(shù)時(shí)淑廊,如果在實(shí)例對(duì)象中找不到,則會(huì)在其原型對(duì)象中查找特咆。這就避免了重復(fù)創(chuàng)建函數(shù)的弊端了~
(這其實(shí)不是純粹的原型模式季惩,而是構(gòu)造函數(shù)和原型組成的新模式。在javascript權(quán)威指南中腻格,原型模式把所有屬性画拾、方法都放在原型對(duì)象上。個(gè)人覺(jué)得這里生硬的拆開(kāi)構(gòu)造函數(shù)和原型有些不妥菜职,會(huì)讓新手困惑青抛。原型、構(gòu)造函數(shù)酬核、實(shí)例對(duì)象的關(guān)系可以查看我的另一篇博文http://www.reibang.com/p/753322534214