JavaScript創(chuàng)建對(duì)象的常用方式總結(jié)
本文實(shí)例講述了JavaScript創(chuàng)建對(duì)象的常用方式。分享給大家供大家參考,具體如下:
JS中沒(méi)有類(lèi)的概念,那么怎么創(chuàng)建對(duì)象呢?下面一一來(lái)細(xì)說(shuō)!
傳統(tǒng)的創(chuàng)建對(duì)象的方式:
1、創(chuàng)建Object的實(shí)例
var person = new Object();
person.name = "Alice";
person.age = 12;
person.showName = function() {
alert(this.name);
};
2、對(duì)象字面量形式創(chuàng)建單個(gè)對(duì)象
var person = {
name : "Alice";
age : 12;
showName : function() {
alert(person.name);
}
};
創(chuàng)建對(duì)象的五種設(shè)計(jì)模式
1、工廠(chǎng)模式
雖然Object構(gòu)造函數(shù)和對(duì)象字面量都可以用來(lái)創(chuàng)建單個(gè)對(duì)象,但這個(gè)方式有個(gè)明顯的缺點(diǎn):使用同一個(gè)接口創(chuàng)建很多對(duì)象,會(huì)產(chǎn)生大量重復(fù)的代碼。為了解決這個(gè)問(wèn)題,開(kāi)始使用工廠(chǎng)模式。
function createPerson(name, age) {
var obj = new Object();
obj.name = name;
obj.age = age;
obj.showName = function() {
alert(this.name);
};
return obj;
}
var person1 = createPerson("Alice", 23);
var person2 = createPerson("Bruce", 22);
2、構(gòu)造函數(shù)模式
工廠(chǎng)模式雖然解決了創(chuàng)建多個(gè)相似對(duì)象的問(wèn)題,但卻沒(méi)有解決對(duì)象識(shí)別的問(wèn)題(即不知道對(duì)象的類(lèi)型),于是,又出現(xiàn)了構(gòu)造函數(shù)模式,自定義的構(gòu)造函數(shù)意味著將來(lái)可以把它的實(shí)例識(shí)別為一種特定的類(lèi)型。這是構(gòu)造函數(shù)模式勝過(guò)工廠(chǎng)模式的地方。
function Person(name, age) {
this.name = name;
this.age = age;
this.showName = function() {
alert(this.name);
};
}
var person1 = new Person("Alice", 23);
var person2 = new Person("Bruce", 22);
構(gòu)造函數(shù)模式與工廠(chǎng)模式的不同之處在于:
1)沒(méi)有顯式地創(chuàng)建對(duì)象;
2)直接將屬性和方法賦給了this對(duì)象;
3)沒(méi)有return語(yǔ)句
構(gòu)造函數(shù)的問(wèn)題:每個(gè)方法都要在每個(gè)實(shí)例上重新創(chuàng)建一遍。由于JavaScript中的函數(shù)是對(duì)象,每定義一個(gè)函數(shù),就是實(shí)例化了一個(gè)Funtion對(duì)象,因此,使用構(gòu)造函數(shù)創(chuàng)建的每個(gè)實(shí)例都有一個(gè)名為showName()的方法,但這些方法不是同一個(gè)Function的實(shí)例。不同實(shí)例上的同名函數(shù)是不相等的,因此person1.showName == person2.showName返回false。
可以通過(guò)把函數(shù)定義轉(zhuǎn)移到構(gòu)造函數(shù)外部來(lái)解決這個(gè)問(wèn)題,如下:
function Person(name,age,job) {
this.name = name;
this.age = age;
this.showName = showName;
}
function showName(){
alert(this.name);
}
var person1 = new Person("Alice", 23);
var person2 = new Person("Bruce", 22);
這樣雖然解決了方法多次創(chuàng)建問(wèn)題,但又出現(xiàn)了新的問(wèn)題:
(1)在全局作用域中定義的函數(shù)實(shí)際上只能被某個(gè)對(duì)象調(diào)用,這讓全局作用域名不副實(shí)。
(2)如果對(duì)象需要定義很多方法,那么就需要定義很多個(gè)全局函數(shù),那么就毫無(wú)封裝性可言了。
這些問(wèn)題可以通過(guò)使用原型模式來(lái)解決。
3、原型模式
每個(gè)函數(shù)都以一個(gè)原型prototype屬性,是一個(gè)指針,指向一個(gè)對(duì)象。
使用原型對(duì)象的好處是可以讓所有對(duì)象實(shí)例共享它所包含的屬性和方法。也就是說(shuō),不必在構(gòu)造函數(shù)中定義對(duì)象實(shí)例的信息,而是可以直接將這些信息添加到原型對(duì)象中。
function Person() {
}
Person.prototype.name = name;
Person.prototype.age = age;
Person.prototype.showName = function(){
alert(this.name);
};
var person1 = new Person();
var person2 = new Person();
使用原型模式創(chuàng)建的新對(duì)象具有相同的屬性和方法。與構(gòu)造函數(shù)模式不同的是,新對(duì)象的這些屬性和方法是由所有對(duì)象所共享的。這會(huì)導(dǎo)致所有實(shí)例默認(rèn)有一樣的屬性值,因此person1.showName == person2.showName返回true。
讀取某個(gè)對(duì)象的某個(gè)屬性的搜索方法:
1)首先在實(shí)例中搜索,若找到指定屬性,則返回該屬性的值。
2)否則繼續(xù)搜索指針指向的原型對(duì)象。
使用delete 實(shí)例名.屬性名可以刪除實(shí)例的某一屬性。
使用hasOwnProperty()方法可以判斷屬性是存在于實(shí)例中,還是存在于原型中。只有給定屬性存在于實(shí)例中,才會(huì)返回true。
in操作符會(huì)在通過(guò)對(duì)象能夠訪(fǎng)問(wèn)給定屬性時(shí)返回true,無(wú)論該屬性存在于實(shí)例中還是原型中。
同時(shí)使用hasOwnProperty()方法和in操作符,能夠確定屬性到底是存在于對(duì)象中,還是存在于原型中。
function Person () {
}
Person.prototype.name = "Alice";
Person.prototype.age = "22";
Person.prototype.showName = function(){
alert(this.name);
};
var person1 = new Person();
var person2 = new Person();
person1.name = "Bruce";
alert(person1.name);//Bruce
alert(person1.hasOwnProperty("name"));//true
alert("name" in person1);//true
alert(person2.name);//Alice
delete person1.name;
alert(person1.hasOwnProperty("name"));//false
alert("name" in person1);//true
alert(person1.name);//Alice
原型模式更簡(jiǎn)單的語(yǔ)法:以一個(gè)包含所有屬性和方法的對(duì)象字面量來(lái)創(chuàng)建原型對(duì)象。
function Person () {
}
Person.prototype = {
name:"Alice",
age : "22",
showName: function(){
alert(this.name);
}
};
用對(duì)象字面量來(lái)創(chuàng)建原型對(duì)象的結(jié)果相同,只是constructor屬性不再指向Person。這是由于這樣已經(jīng)完全重寫(xiě)了默認(rèn)的prototype對(duì)象,因此constructor屬性也就變成了新對(duì)象的constructor屬性,指向Object構(gòu)造函數(shù)但不指向Person函數(shù)。此時(shí),instanceof操作符還能返回正確的結(jié)果但通過(guò)constructor已經(jīng)無(wú)法確定對(duì)象的類(lèi)型了。
var person = new Person(); alert(person instanceof Object);//true alert(person instanceof Person);//true alert(person.constructor == Object);//true alert(person.constructor == Person);//false
如果constuctor的值很重要,可以特意將其設(shè)置回適當(dāng)?shù)闹怠?/p>
function Person () {
}
Person.prototype = {
constructor:Person,
name:"Alice",
age : "22",
showName: function(){
alert(this.name);
}
};
重寫(xiě)原型對(duì)象切斷了現(xiàn)有原型與任何之前已經(jīng)存在的對(duì)象實(shí)例之間的聯(lián)系,對(duì)象實(shí)例引用的仍然是最初的原型。
function Person () {
}
var person = new Person();
Person.prototype = {
constructor:Person,
name:"Alice",
age : "22",
showName: function(){
alert(this.name);
}
};
person.showName();//報(bào)錯(cuò):person.showName is not a function
4、組合使用構(gòu)造函數(shù)模式和原型模式
原型對(duì)象的問(wèn)題:最大問(wèn)題是由于共享屬性導(dǎo)致的。原型中所有屬性是被實(shí)例共享的,這對(duì)于函數(shù)很合適,對(duì)那些包含基本值的屬性也還說(shuō)得過(guò)去,因?yàn)榭梢酝ㄟ^(guò)在實(shí)例上添加同名屬性,隱藏原型中的對(duì)應(yīng)屬性。然而,對(duì)于包含引用值的屬性來(lái)說(shuō),問(wèn)題就比較突出了,修改某個(gè)實(shí)例的引用類(lèi)型的屬性也會(huì)通過(guò)原型影響到其它實(shí)例的該屬性。
創(chuàng)建自定義類(lèi)型的最常見(jiàn)方法是組合使用構(gòu)造函數(shù)模式和原型模式,構(gòu)造函數(shù)模式用于定義實(shí)例屬性,原型模式用于定義方法和共享的屬性。
function Person(name, age) {
this.name = name;
this.age = age;
this.friends = ["Bruce", "Cindy"];
}
Person.prototype = {
constructor : Person,
showName : function(){
alert(this.name);
}
};
var person1 = new Person("Alice",23);
var person2 = new Person("David",22);
person1.friends.push("Vincy");//包含引用值的屬性friends
alert(person1.friends);//"Bruce", "Cindy","Vincy"
alert(person2.friends);//"Bruce","Cindy"
alert(person1.friends == person2.friends);//false
alert(person1.showName == person2.showName);//true
5、動(dòng)態(tài)原型模式
動(dòng)態(tài)原型模式把所有信息都封裝在了構(gòu)造函數(shù)中,而通過(guò)在構(gòu)造函數(shù)中初始化原型,又保持了同時(shí)使用構(gòu)造函數(shù)和原型的優(yōu)點(diǎn)。
可以通過(guò)檢查某個(gè)應(yīng)該存在的方法是否有效,來(lái)決定是否需要初始化原型。
如:只在showName()方法不存在的情況下,才會(huì)將它添加到原型中,這段代碼只會(huì)在初次調(diào)用構(gòu)造函數(shù)時(shí)才會(huì)執(zhí)行。
function Person(name,age) {
this.name=name;
this.age=age;
if(typeof this.showName!="function"){
Person.prototype.showName=function(){
alert(this.name);
}
}
}
alert(person1.hasOwnProperty("name"));//true
更多關(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ì)有所幫助。
- js 創(chuàng)建對(duì)象的多種方式與優(yōu)缺點(diǎn)小結(jié)
- 詳解js創(chuàng)建對(duì)象的幾種方式和對(duì)象方法
- javascript面向?qū)ο髣?chuàng)建對(duì)象的方式小結(jié)
- JS中的函數(shù)與對(duì)象的創(chuàng)建方式
- JavaScript創(chuàng)建對(duì)象方式總結(jié)【工廠(chǎng)模式、構(gòu)造函數(shù)模式、原型模式等】
- JavaScript實(shí)現(xiàn)創(chuàng)建自定義對(duì)象的常用方式總結(jié)
- JavaScript創(chuàng)建對(duì)象的七種方式全面總結(jié)
- 基于JS對(duì)象創(chuàng)建常用方式及原理分析
- JavaScript創(chuàng)建對(duì)象的七種方式(推薦)
- JS創(chuàng)建對(duì)象的四種方式
相關(guān)文章
原生JS實(shí)現(xiàn)隱藏顯示圖片 JS實(shí)現(xiàn)點(diǎn)擊切換圖片效果
這篇文章主要為大家詳細(xì)介紹了原生JS實(shí)現(xiàn)隱藏顯示圖片,JS實(shí)現(xiàn)點(diǎn)擊切換圖片效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07
JavaScript嚴(yán)格模式禁用With語(yǔ)句的原因
看了很多遍JavaScript嚴(yán)格模式,其中有說(shuō)“禁用With語(yǔ)句”今天禁不住想知道為何“嚴(yán)格模式”就容不下with語(yǔ)句呢,如果你也表示疑惑可以看看哦2014-10-10
js中實(shí)現(xiàn)字符串和數(shù)組的相互轉(zhuǎn)化詳解
這篇文章主要介紹了js中實(shí)現(xiàn)字符串和數(shù)組的相互轉(zhuǎn)化,感興趣的小伙伴們可以參考一下2016-01-01
查找頁(yè)面中所有類(lèi)為test的結(jié)點(diǎn)的方法
這篇文章主要介紹了查找頁(yè)面中所有類(lèi)為test結(jié)點(diǎn)的方法,需要的朋友可以參考下2014-03-03
JS匿名函數(shù)和匿名自執(zhí)行函數(shù)概念與用法分析
這篇文章主要介紹了JS匿名函數(shù)和匿名自執(zhí)行函數(shù)概念與用法,結(jié)合實(shí)例形式分析了匿名函數(shù)和匿名自執(zhí)行函數(shù)的概念、功能、應(yīng)用場(chǎng)景及相關(guān)使用技巧,需要的朋友可以參考下2018-03-03
前端js實(shí)現(xiàn)文件的斷點(diǎn)續(xù)傳 后端PHP文件接收
這篇文章主要為大家詳細(xì)介紹了斷點(diǎn)續(xù)傳的簡(jiǎn)單例子,前端文件提交,后端PHP文件接收,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10
js 彈出對(duì)話(huà)框(遮罩)透明,可拖動(dòng)的簡(jiǎn)單實(shí)例
下面小編就為大家?guī)?lái)一篇js 彈出對(duì)話(huà)框(遮罩)透明,可拖動(dòng)的簡(jiǎn)單實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-07-07

