本文實例講述了JavaScript創(chuàng)建對象的常用方式。分享給大家供大家參考,具體如下:
JS中沒有類的概念,那么怎么創(chuàng)建對象呢?下面一一來細說!
傳統(tǒng)的創(chuàng)建對象的方式:
1、創(chuàng)建Object的實例
var person = new Object();person.name = "Alice";person.age = 12;person.showName = function() { alert(this.name);};2、對象字面量形式創(chuàng)建單個對象
var person = { name : "Alice"; age : 12; showName : function() {  alert(person.name); }};創(chuàng)建對象的五種設(shè)計模式
1、工廠模式
雖然Object構(gòu)造函數(shù)和對象字面量都可以用來創(chuàng)建單個對象,但這個方式有個明顯的缺點:使用同一個接口創(chuàng)建很多對象,會產(chǎn)生大量重復的代碼。為了解決這個問題,開始使用工廠模式。
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ù)模式
工廠模式雖然解決了創(chuàng)建多個相似對象的問題,但卻沒有解決對象識別的問題(即不知道對象的類型),于是,又出現(xiàn)了構(gòu)造函數(shù)模式,自定義的構(gòu)造函數(shù)意味著將來可以把它的實例識別為一種特定的類型。這是構(gòu)造函數(shù)模式勝過工廠模式的地方。
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ù)模式與工廠模式的不同之處在于:
1)沒有顯式地創(chuàng)建對象;
2)直接將屬性和方法賦給了this對象;
	3)沒有return語句
	構(gòu)造函數(shù)的問題:每個方法都要在每個實例上重新創(chuàng)建一遍。由于JavaScript中的函數(shù)是對象,每定義一個函數(shù),就是實例化了一個Funtion對象,因此,使用構(gòu)造函數(shù)創(chuàng)建的每個實例都有一個名為showName()的方法,但這些方法不是同一個Function的實例。不同實例上的同名函數(shù)是不相等的,因此person1.showName == person2.showName返回false。
可以通過把函數(shù)定義轉(zhuǎn)移到構(gòu)造函數(shù)外部來解決這個問題,如下:
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)建問題,但又出現(xiàn)了新的問題:
(1)在全局作用域中定義的函數(shù)實際上只能被某個對象調(diào)用,這讓全局作用域名不副實。
(2)如果對象需要定義很多方法,那么就需要定義很多個全局函數(shù),那么就毫無封裝性可言了。
這些問題可以通過使用原型模式來解決。
3、原型模式
每個函數(shù)都以一個原型prototype屬性,是一個指針,指向一個對象。
使用原型對象的好處是可以讓所有對象實例共享它所包含的屬性和方法。也就是說,不必在構(gòu)造函數(shù)中定義對象實例的信息,而是可以直接將這些信息添加到原型對象中。
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)建的新對象具有相同的屬性和方法。與構(gòu)造函數(shù)模式不同的是,新對象的這些屬性和方法是由所有對象所共享的。這會導致所有實例默認有一樣的屬性值,因此person1.showName == person2.showName返回true。
讀取某個對象的某個屬性的搜索方法:
1)首先在實例中搜索,若找到指定屬性,則返回該屬性的值。
2)否則繼續(xù)搜索指針指向的原型對象。
使用delete 實例名.屬性名可以刪除實例的某一屬性。
	使用hasOwnProperty()方法可以判斷屬性是存在于實例中,還是存在于原型中。只有給定屬性存在于實例中,才會返回true。
in操作符會在通過對象能夠訪問給定屬性時返回true,無論該屬性存在于實例中還是原型中。
	同時使用hasOwnProperty()方法和in操作符,能夠確定屬性到底是存在于對象中,還是存在于原型中。
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);//Brucealert(person1.hasOwnProperty("name"));//truealert("name" in person1);//truealert(person2.name);//Alicedelete person1.name;alert(person1.hasOwnProperty("name"));//falsealert("name" in person1);//truealert(person1.name);//Alice原型模式更簡單的語法:以一個包含所有屬性和方法的對象字面量來創(chuàng)建原型對象。
function Person () {}Person.prototype = {  name:"Alice",  age : "22",  showName: function(){   alert(this.name);  }};用對象字面量來創(chuàng)建原型對象的結(jié)果相同,只是constructor屬性不再指向Person。這是由于這樣已經(jīng)完全重寫了默認的prototype對象,因此constructor屬性也就變成了新對象的constructor屬性,指向Object構(gòu)造函數(shù)但不指向Person函數(shù)。此時,instanceof操作符還能返回正確的結(jié)果但通過constructor已經(jīng)無法確定對象的類型了。
var person = new Person();alert(person instanceof Object);//truealert(person instanceof Person);//truealert(person.constructor == Object);//truealert(person.constructor == Person);//false
如果constuctor的值很重要,可以特意將其設(shè)置回適當?shù)闹怠?/p>
function Person () {}Person.prototype = { constructor:Person,  name:"Alice",  age : "22",  showName: function(){   alert(this.name);  }};重寫原型對象切斷了現(xiàn)有原型與任何之前已經(jīng)存在的對象實例之間的聯(lián)系,對象實例引用的仍然是最初的原型。
function Person () {}var person = new Person();Person.prototype = { constructor:Person, name:"Alice", age : "22", showName: function(){  alert(this.name); }};person.showName();//報錯:person.showName is not a function4、組合使用構(gòu)造函數(shù)模式和原型模式
原型對象的問題:最大問題是由于共享屬性導致的。原型中所有屬性是被實例共享的,這對于函數(shù)很合適,對那些包含基本值的屬性也還說得過去,因為可以通過在實例上添加同名屬性,隱藏原型中的對應屬性。然而,對于包含引用值的屬性來說,問題就比較突出了,修改某個實例的引用類型的屬性也會通過原型影響到其它實例的該屬性。
創(chuàng)建自定義類型的最常見方法是組合使用構(gòu)造函數(shù)模式和原型模式,構(gòu)造函數(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");//包含引用值的屬性friendsalert(person1.friends);//"Bruce", "Cindy","Vincy"alert(person2.friends);//"Bruce","Cindy"alert(person1.friends == person2.friends);//falsealert(person1.showName == person2.showName);//true5、動態(tài)原型模式
動態(tài)原型模式把所有信息都封裝在了構(gòu)造函數(shù)中,而通過在構(gòu)造函數(shù)中初始化原型,又保持了同時使用構(gòu)造函數(shù)和原型的優(yōu)點。
可以通過檢查某個應該存在的方法是否有效,來決定是否需要初始化原型。
	如:只在showName()方法不存在的情況下,才會將它添加到原型中,這段代碼只會在初次調(diào)用構(gòu)造函數(shù)時才會執(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希望本文所述對大家JavaScript程序設(shè)計有所幫助。
新聞熱點
疑難解答