javascript物件導向的建立對象筆記

來源:互聯網
上載者:User

1原廠模式:
原廠模式是軟體工程領域一種廣為人知的設計模式,這種模式抽象了建立具體對象的過程。由於ECMAScript無法建立類,所以開發人員就發明一種函數,用函數來封裝以特定介面建立對象的細節。如下:

 代碼如下 複製代碼

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(“gothic”,”21″,”f2e”);
var person2 =createPerson(“greg”,”27″,”Doctor”);

這裡函數creatPerson()能夠根據接受的參數來構建一個包含所有必要資訊的person對象,可以無數次的調用這個函數,而每次它都會返回一個包含三個屬性一個方法的對象。原廠模式雖然解決了建立多個相識對象的問題,但是卻沒有解決對象識別的問題(即如何讓知道一個對象的類型),所以又有了下面的模式。
2.建構函式模式
ECMAScript中的函數可用來建立特定類型的對象。像Object和Array這樣的原生建構函式,在運行時會自動出現在執行環境中。當然我們也可以建立自訂的建構函式,從而定義 自訂物件類型的屬性和方法。如下:

 代碼如下 複製代碼

function person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
alert(this.name)
};
}
var person1 = new Person(“gothic”,21,”f2e”);
var person2 = new Person(“greg”,27,”Doctor”);

這裡用建構函式模式把上面的例子重寫了一遍。下面我們看下兩個寫法的區別:
Person()中的代碼與CreatePerson()中的除了相同部分,還有以下不同
1)沒有顯示的建立對象;
2)直接將屬性和方法賦予了this對象;
3)沒有return語句。
PS:按照慣例,建構函式始終都應該以一個大寫字母開頭,而非建構函式則應該以一個小寫字母開頭。不過建構函式本身也是函數,只是可以用來建立對象而已。
Constructor:建構函式屬性。對象的constructor最初是用來標識物件類型的。但是要檢測物件類型,還是用instanceof操作靠譜一點,如下:

 代碼如下 複製代碼
alert(person1 instanceof Object); //true
alert(person2 instanceof Object); //true

建立自訂的建構函式意味著將來可以將它的執行個體標識為一種特定的類型,而這正是建構函式模式勝過原廠模式的地方。這個例子裡:
person1和person2之所以同時是Object的執行個體,是因為所有對象均繼承自Object。

建構函式和其他函數的唯一區別就在於調用它們的方式不同。任何函數,只要通過new操作符來調用,那它就可以作為建構函式,而任何函數如果不通過new操作符來調用,那它和普通函數也不會有什麼兩樣。用前面的例子舉例:

 代碼如下 複製代碼

//當作建構函式使用
var person = new Person(“gothic”,21,”f2e”);
person.sayName();//”gothic”

//作為普通函數調用 www.111cn.net
Person(“greg”,27,”Doctor”);
windows.sayName();//”greg”

//在另一個對象的範圍中調用
var o = new Object();
person.call(o,”K0risten”,25,”Nurse”);
o.sayName();//”kristen”

建構函式模式雖然好用,但是也不是沒有缺點。它的主要問題就是每個方法都要在每個執行個體上重新建立一遍。說明白點就是這種方式建立函數,會導致不同的範圍和標識符解析,但建立function新執行個體的機制是相同的。因此不同執行個體上的同名函數是不想等的,可以用下面這個判斷下:
alert(person1.sayName == person2.sayName); //false

3.原型模式
我們建立的每一個函數都有一個prototype(原型)屬性,這個屬性是一個指標,指向一個對象,這個對象的用途就是包含可以由特定類型的所有執行個體共用的屬性和方法。使用原型對象的好處就是可以讓所有對象執行個體共用它所包含的屬性和方法。說明白點就是沒必要在建構函式中定義對象執行個體的資訊,而是可以將這些資訊直接添加到原型對象中,如下:

 代碼如下 複製代碼

function Person(){
}
person.prototype.name = “gothic”;
Person.prototype.age = 21;
Person.prototype.job =”f2e”;
Person.prototype.sayName = function(){
alert(this.name);

}
var person1 = new Person();
person1.sayName(); //”gothic”
var person2 = new Person();
person2.sayName(); //”gothic”
alert(person1.sayName == person2.sayName); //true

要理解原型模式的工作原理,必須要先理解ECMAScript中原型對象的性質。
原型模式也有缺點,它省略了為建構函式傳遞初始化參數這一環節,結果所有執行個體在預設情況下都將取得相同的屬性值。原型模式最大的問題是由其共用的本性所導致的。
因為原型中所有屬性是被很多執行個體共用的,這種共用對於函數很合適,但是對於包含參考型別值的屬性來說,問題就比較突出,如下:

 代碼如下 複製代碼

function(){

}
Person.prototype ={
constructor:Person,
name:”gothic”,
age:21,
job:”f2e”
friends:["Shelby","Court"],
sayName:function(){
alert(this.name);
}
} www.111cn.net
var person1 = new Person();
var person2 = new Person();
person1.friends.push(“Van”);
alert(person1.friends); //”Shelby,Court,Van”
alert(person2.friends); //”Shelby,Court,Van”
alert(person1.friends == person2.friends); //true

上面代碼我們可以看到Person.prototype對象有一個名為friends屬性,該屬性包含一個字串組,然後建立了Person的兩個執行個體,向person1.friends引用的數組添加了一個字串。由於friends數組存在於Person.prototype而不是person1裡,所以剛剛添加修改的也會通過person2.friends反映出來。但是有時我們並不想讓它在person2.prototype裡反映,執行個體一般都有屬於自己的屬性。

4.組合使用建構函式模式和原型模式
建立自訂類型的最常見方式,就是組合使用建構函式模式與原型模式。建構函式模式用於定義執行個體屬性,而原型模式用於定義方法和共用的屬性。這樣的好處就是每個執行個體都會有自己的一份執行個體屬性的副本,但同時又共用著對方的引用,最大限度的節省了記憶體,而且這種混合模式還支援向建構函式傳遞參數;如下:

 代碼如下 複製代碼

function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.friends=["SHelby","Court"];
}
Person.prototype = {
constructor:Person,
sayName:function(){
alert(this.name);
}
}
var person1 =new Person(“gothic”,21,”f2e”);
var person2 =new Person(“greg”,27,”Doctor”);
person1.friends.push(“Van”);
alert(person1.friends); //”Shelby,Count,Van”
alert(person2.friends); //”Shelby,Court”
alert(person1.friends === person2.friends); //false
alert(person2.friends === person2.friends); //true

這種建構函式與原型混成的模式是目前使用最為廣泛,認同度較高的方法。

5動態原型模式
動態原型模式它把所有資訊都封裝在了建構函式中,而通過在建構函式中初始化原型,又保持了同時使用建構函式和原型的優點。如下:

 代碼如下 複製代碼

function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
if(typeof this.sayName != “function”){
Person.prototype.sayName = function(){
alert(this.name);
};
}
}
var friend = new Person(“gothic”,21,”f2e”);
friends.sayName();

上面代碼裡的if語句只有在sayName()方法不存在的情況下,才會將它添加到原型中。這段代碼只會在初次調用建構函式時才會執行。此後,原型已經完成初始化,不要再做什麼修改了。
6.寄生建構函式模式
如果再上述幾種模式下都不適用的情況下可以試試寄生建構函式模式
這個模式基本思想就是建立一個函數,該函數的作用僅僅是封裝建立對象的代碼,然後再返回新建立的對象。如下:

 代碼如下 複製代碼

function Person(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 friends = new Person(“gothic”,21,”f2e”);
friends.sayName() //”gothic”

這裡除了使用new操作符並把使用的封裝函數叫做建構函式之外,這個模式跟原廠模式其實是一模一樣的。狗造函數在不傳回值的情況下,會預設返回新對象執行個體。而通過在建構函式的末尾添加一個return語句,可以重寫調用建構函式時返回的值。
這個模式可以在特殊的時候用來為對象建立建構函式

關於寄生建構函式模式我們要注意:返回的對象魚建構函式或者與建構函式的原型屬性之間沒有關係;也就是說,建構函式返回的對象與在建構函式外部建立的對象沒有什麼不同。也就是不能依靠instanceof操作符來確定物件類型,所以我建議還是不要使用這個模式。
7.穩妥建構函式模式
我們的Douglas同學發明了js中的“穩妥對象”這個概念.所謂的穩妥對象指的是沒有公用屬性,而且其方法也不引用this的對象,穩妥對象適合在一些安全的環境中使用。穩妥模式函數模式遵循與寄生建構函式類似的模式(也就是說instanceof操作符對這種對象也沒用),但有兩點不同:一是新建立的對象的執行個體方法不引用this,二是不使用new操作符調用建構函式。按穩妥模式的要求,我們可以重寫:

 代碼如下 複製代碼

function Person(name,age,job){
var o =new Object();
o.sayName = function(){
alert(name);
};
return o;
}

以上這個模式建立的對象除了使用sayName()方法之外,沒有其他辦法訪問name的值。我們可以想下面使用穩妥的person建構函式。

 代碼如下 複製代碼
var friend = Person(“gothic”,21,”f2e”);
friends.sayName(); //gothic

這樣friends儲存的是一個穩妥對象,除了調用sayName()方法外,沒有別的方法可以訪問器資料成員。所以說穩妥模式適合在某些安全執行環境下使用。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.