JavaScript實(shí)現(xiàn)創(chuàng)建自定義對(duì)象的常用方式總結(jié)
本文實(shí)例講述了JavaScript實(shí)現(xiàn)創(chuàng)建自定義對(duì)象的常用方式。分享給大家供大家參考,具體如下:
1. 對(duì)象字面量方式
對(duì)象字面量方式是創(chuàng)建自定義對(duì)象的首選模式,簡(jiǎn)單方便。
var per = {
name:'zhangsan',
age:25,
job:'html',
sayName:function(){
alert(this.name);
}
}
缺點(diǎn):使用同一個(gè)接口創(chuàng)建很多對(duì)象,會(huì)產(chǎn)生大量的重復(fù)代碼。比如我想再創(chuàng)建一個(gè)per1對(duì)象,我就得把上面的代碼再重新寫(xiě)一遍,改變不同的屬性值。
2、工廠模式
工廠模式抽象了創(chuàng)建具體對(duì)象的過(guò)程。由于在ECMAScript中無(wú)法創(chuàng)建類(lèi),開(kāi)發(fā)人員就發(fā)明了一種函數(shù),用函數(shù)來(lái)封裝以特定接口創(chuàng)建對(duì)象的細(xì)節(jié),如下面的例子:
function createPerson(name,age,job){
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function(){
alert(this.name);
}
return o;
}
var person1 = createPerson('zhang',30,'java');
var person2 = createPerson('zhao',25,'php');
函數(shù)createPerson()能夠根據(jù)接受到的參數(shù)來(lái)構(gòu)建一個(gè)包含所有必要信息的Person對(duì)象??梢詿o(wú)數(shù)次的調(diào)用這個(gè)函數(shù),而每次它都會(huì)返回一個(gè)包含三個(gè)屬性和一個(gè)方法的對(duì)象。
缺點(diǎn):工廠模式雖然解決了創(chuàng)建多個(gè)相似對(duì)象的問(wèn)題,但卻沒(méi)有解決對(duì)象識(shí)別的問(wèn)題(即怎樣知道一個(gè)對(duì)象的類(lèi)型)。
3、構(gòu)造函數(shù)模式
可以使用構(gòu)造函數(shù)模式將前面的例子重寫(xiě)如下:
function Person(name,age,job){
this.name= name;
this.age = age;
this.job = job;
this.sayName = function(){
alert(this.name);
}
}
var person1 = new Person('zhang',30,'java');
var person2 = new Person('zhao',25,'php');
創(chuàng)建自定義的構(gòu)造函數(shù)意味著將來(lái)可以將它的實(shí)例標(biāo)識(shí)為一種特定的類(lèi)型。而這正是構(gòu)造函數(shù)模式勝過(guò)工廠模式的地方。
然而,使用構(gòu)造函數(shù)的主要問(wèn)題,就是每個(gè)方法都要在每個(gè)實(shí)例上重新創(chuàng)建一遍。在上面的例子中,person1和person2都有一個(gè)名為sayName()的方法,但那兩個(gè)方法不是同一個(gè)Function的實(shí)例,創(chuàng)建兩個(gè)完成同樣任務(wù)的Function實(shí)例的確沒(méi)有必要;況且有this對(duì)象在,根本不用在執(zhí)行代碼前就把函數(shù)綁定到特定對(duì)象上面。因此可以像下面這樣,通過(guò)把函數(shù)定義轉(zhuǎn)移到構(gòu)造函數(shù)外部來(lái)解決這個(gè)問(wèn)題。
function Person(name,age,job){
this.name= name;
this.age = age;
this.job = job;
this.sayName = sayName();
}
function sayName(){
alert(this.name);
}
var person1 = createPerson('zhang',30,'java');
var person2 = createPerson('zhao',25,'php');
在這個(gè)例子中,我們把sayName()函數(shù)的定義轉(zhuǎn)移到構(gòu)造函數(shù)外部。而在構(gòu)造函數(shù)內(nèi)部,我們將sayName屬性設(shè)置成等于全局的sayName函數(shù),這樣person1和person2對(duì)象就共享了在全局作用域中定義的同一個(gè)sayName()函數(shù)。這樣確實(shí)解決了兩個(gè)函數(shù)在做同一件事的問(wèn)題,可是新問(wèn)題又來(lái)了:在全局作用域中定義的函數(shù)實(shí)際上只能被某個(gè)對(duì)象調(diào)用,這讓全局作用域有點(diǎn)名不副實(shí)。更讓人無(wú)法接受的是:如果對(duì)象需要定義很多方法,那么就要定義很多全局函數(shù)。好在,這些問(wèn)題可以通過(guò)使用原型模式來(lái)解決。
4、原型模式
我們創(chuàng)建的每個(gè)函數(shù)都有一個(gè)prototype(原型)屬性,這個(gè)屬性是一個(gè)指針,指向一個(gè)對(duì)象,而這個(gè)對(duì)象的用途是包含可以由特定類(lèi)型的所有實(shí)例共享的屬性和方法。使用原型對(duì)象的好處是可以讓所有的對(duì)象實(shí)例共享他所包含的屬性和方法。
function Person(){}
Person.prototype.name = 'zhang';
Person.prototype.age = '22';
Person.prototype.job = 'html5';
Person.prototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
var person2 = new Person();
原型模式也不是沒(méi)有缺點(diǎn)。首先,它省略了為構(gòu)造函數(shù)傳遞初始化參數(shù)這一環(huán)節(jié),結(jié)果所有實(shí)例在默認(rèn)情況下都將取得相同的屬性值。雖然這會(huì)在某種程度上帶來(lái)一些不方便,但還不是原型的最大問(wèn)題。原型模式的最大問(wèn)題是由共享的本性所導(dǎo)致的。
原型中所有屬性是被很多實(shí)例共享的,這種共享對(duì)于函數(shù)非常合適。對(duì)于那些包含基本值的屬性倒也說(shuō)的過(guò)去,通過(guò)在實(shí)例上添加一個(gè)同名屬性,可以隱藏原型中的對(duì)應(yīng)屬性。然后,對(duì)于包含引用類(lèi)型的屬性來(lái)說(shuō),問(wèn)題就比較突出了。
function Person(){}
Person.prototype = {
constructor:Person,
name:'zhang',
age :'22',
job :'html5',
friends:['wang','li'],
sayName : function(){
alert(this.name);
}
};
var person1 = new Person();
var person2 = new Person();
person1.friends.push('zhao');
alert(person1.friends); //'wang,li,zhao'
alert(person2.friends); //'wang,li,zhao'
alert(person1.friends === person2.friends); //true
從上面的打印的結(jié)果我們就可以知道為什么很少人單獨(dú)使用原型模式了,實(shí)例一般都是要有屬于自己的全部屬性的。
5、組合使用構(gòu)造函數(shù)模式和原型模式
組合使用構(gòu)造函數(shù)模式和原型模式,是創(chuàng)建自定義類(lèi)型的最常見(jiàn)方式。構(gòu)造函數(shù)模式用于定義實(shí)例屬性,而原型模式用于定義方法和共享的屬性。結(jié)果,每個(gè)實(shí)例都會(huì)有自己的一份實(shí)例屬性的副本,但同時(shí)又共享著對(duì)方法的引用,最大限度的節(jié)省了內(nèi)存。
function Person(name,age,job){
this.name= name;
this.age = age;
this.job = job;
this.friends = ['wang','li'];
}
Person.prototype = {
constructor:Person,
sayName : function(){
alert(this.name);
}
}
var person1 = new Person('zhang',26,'java',);
var person2 = new Person('sun',25,'php');
person1.friends.push('zhao');
alert(person1.friends); //'wang,li,zhao'
alert(person2.friends); //'wang,li'
alert(person1.friends === person2.friends); //false
在上面的例子中,實(shí)例屬性都是在構(gòu)造函數(shù)中定義的,而由所有實(shí)例共享的屬性constructor和方法satName()則是在原型中定義的。而修改了person1.friends(向其中添加一個(gè)新字符串),并不會(huì)影響到person2.friends,因?yàn)樗麄兎謩e引用了不同的數(shù)組。
更多關(guān)于JavaScript相關(guān)內(nèi)容感興趣的讀者可查看本站專(zhuān)題:《javascript面向?qū)ο笕腴T(mén)教程》、《JavaScript錯(cuò)誤與調(diào)試技巧總結(jié)》、《JavaScript數(shù)據(jù)結(jié)構(gòu)與算法技巧總結(jié)》、《JavaScript遍歷算法與技巧總結(jié)》及《JavaScript數(shù)學(xué)運(yùn)算用法總結(jié)》
希望本文所述對(duì)大家JavaScript程序設(shè)計(jì)有所幫助。
相關(guān)文章
php+js實(shí)現(xiàn)倒計(jì)時(shí)功能
由PHP傳入JS處理的時(shí)間戳我說(shuō)怎么老是對(duì)不上號(hào)呢,原來(lái)JS時(shí)間戳為13位,包含3位毫秒的,而PHP只有10位不包含毫秒的。恩,基礎(chǔ)還是要補(bǔ)補(bǔ)的2014-06-06
JavaScript+html實(shí)現(xiàn)前端頁(yè)面滑動(dòng)驗(yàn)證
這篇文章主要為大家詳細(xì)介紹了JavaScript+html實(shí)現(xiàn)前端頁(yè)面滑動(dòng)驗(yàn)證,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06
bootstrapValidator.min.js表單驗(yàn)證插件
這篇文章主要為大家詳細(xì)介紹了bootstrapValidator.min.js表單驗(yàn)證插件的使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02
JavaScript的基礎(chǔ)語(yǔ)法和數(shù)據(jù)類(lèi)型詳解
這篇文章主要介紹了JavaScript的基礎(chǔ)語(yǔ)法和數(shù)據(jù)類(lèi)型,保姆級(jí)的詳細(xì)教程,萬(wàn)字長(zhǎng)文詳細(xì)的列出了JavaScript的各種語(yǔ)法,建議收藏系列,希望可以有所幫助2021-09-09
微信小程序?qū)崿F(xiàn)選擇地址省市區(qū)三級(jí)聯(lián)動(dòng)
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)選擇地址省市區(qū)三級(jí)聯(lián)動(dòng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-06-06
js操作css屬性實(shí)現(xiàn)div層展開(kāi)關(guān)閉效果的方法
這篇文章主要介紹了js操作css屬性實(shí)現(xiàn)div層展開(kāi)關(guān)閉效果的方法,涉及javaScript操作css樣式實(shí)現(xiàn)div彈出層的效果,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-05-05
bootstrap table合并行數(shù)據(jù)并居中對(duì)齊效果
這篇文章主要為大家詳細(xì)介紹了bootstrap table合并行數(shù)據(jù)并居中對(duì)齊效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-10-10

