雖然Object組織函數或對象字面量都能夠用來建立單個對象,然則這些要領有顯著的瑕玷:運用同一個接口建立許多對象,會發生大批反覆代碼。因而人們開始運用工場形式。
工場形式
這類形式籠統了建立詳細對象的歷程
function createPerson(name,age){
var o = new Object();
o.name = name;
o.age = age;
o.sayName = function(){
alert(this.name);
};
return o;
}
var person1 = new createPerson("liaojin",18);
var person2 = new createPerson("xiaoguan",20);
函數createPerson()能夠依據接收的參數來構建一個包括一切必要信息的Person對象。能夠無數次的挪用這個函數,而每次它都邑返回一個包括兩個屬性以個要領的對象。工場形式雖然處理了建立多個相似對象的題目,但卻沒有處理對象辨認的題目(即如何曉得一個對象的範例)。
組織函數形式
運用組織函數將上述例子重寫
function Person(name,age){
this.name = name;
this.age = age;
this.sayName = function(){
alert(this.name);
};
}
var person1 = new Person("liaojin",18);
var person2 = new Person("xiaoguan",20);
在這個例子中,Person()函數庖代了createPerson()函數。注意到Person()中的代碼與createPerson()的差別之處:
1.沒有顯現的建立對象
2.直接將屬性和要領賦值給了this對象
3.沒有return語句
要建立Person新實例,必需運用new操作符。這類體式格局會司理以下四個步驟:
1.建立一個新對象
2.將組織函數的作用域賦給新對象(因而this就指向了這個新對象)
3.實行組織函數中的代碼(為這個新對象增加屬性)
4.返回新對象
person1和person2離別保留着Person的一個差別實例。這兩個對象都有一個constructor屬性,該屬性指向Person。
alert(person1.constructor == Person);//true
alert(person2.constructor == Person);//true
對象的constructor屬性最初是用來示意對象範例的,然則檢測對象範例照樣instanceof更牢靠一些。這個例子中建立的一切對象等於Object的實例,同時也是Person的實例。
建立自定義的組織函數意味着未來能夠將它的實例標識為一種特定的範例;person1和person2之所以同時是Object的實例,是因為一切對象均繼續自Object.
將組織函數當作函數
組織函數與其他函數唯一的區分就在於挪用他們的體式格局差別。
任何函數只需經由過程new操作符來挪用,那他就能夠作為組織函數;而任何函數假如不經由過程new操作符來挪用,那他跟一般函數沒有區分。
如上述例子中的Person()函數能夠經由過程以下任何一種體式格局來挪用。
//當作組織函數挪用
var person = new Person("liaojin",18);
person.sayName();//liaojin
//作為一般函數挪用
Person("lihua",12);
window.sayName();//lihua
//在另一個對象的作用域挪用
var o = new Object();
Person.call(o,"xiaoguan",20);
o.sayName();//xiaoguan
組織函數的題目
組織函數形式雖然好用,然則也有瑕玷。運用組織函數的重要題目,就是每一個要領都要在每一個實例上從新建立一遍。犹如this.sayName =new function(){alert(this.name);};在上面的組織函數中sayName()的要領,person1和person2雖然都挪用了這個要領,然則挪用的並非同一個Function實例。因而差別實例的同名函數是不相等的
alert(person1.sayName == person2.sayName);//false
但是建立兩個完成一樣使命的Function實例確實沒有必要;因而能夠經由過程吧函數定義轉移到組織函數外部來處理這個題目
function Person(name,age){
this.name = name;
this.age = age;
this.sayName = sayName;
}
function sayName(){
alert(this.name);
}
var person1 = new Person("liaojin",18);
var person2 = new Person("xiaoguan",20);
在組織函數內部,我們將sayName屬性設置為指向全局的sayName函數,因為sayName包括的是指向函數的指針,person1,person2同享了一個sayName函數,處理了兩個函數做一樣一件事的題目。
但是隨即有發生了新的題目:在全局作用域定義的函數實際上只能被某個對象挪用,這讓全局函數長處有名無實。假如對象須要定義許多要領,那末就須要定義多個全局函數,因而自定義的援用範例就沒有封裝性可言了,因而發生了原型形式。
原型形式
我們所建立的每一個函數都有一個prototype屬性,這個屬性是一個指針,指向一個對象,而這個對象的用處就是包括能夠由特定範例的一切實例同享的屬性和要領。prototype就是經由過程挪用組織函數而建立的誰人對象實例的原型對象。能夠讓一切對象的實例同享它所包括的屬性和要領。
function Person(){}
Person.prototype.name = "liaojin";
Person.prototype.age = 18;
Person.prototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
Person1.sayName();//liaojin
var person2 = new Person();
Person2.sayName();//liaojin
alert(person1.sayName == person2.sayName);//true
組合運用組織函數形式和原型形式
組織函數用於定義實例屬性,而原型形式用於定義要領和同享的屬性。如許每一個實例都邑有本身的實例屬性的副本,但同時又同享着對要領的援用,最大限制地節省了內存。
function Person(name,age){
this.name = name;
this.age = age;
this.friends = ["lucy","lily"];
}
Person.prototype = {
constructor:Person,
sayName:function(){
alert(this.name);
}
}
var person1 = new Person("liaojin",18);
var person2 = new Person("xiaoguan",20);
person1.friends.push("lihua");
alert(person1.friends);//lucy,lily,lihua
alert(person2.friends);//lucy,lily
alert(person1.friends == person2.friends);//false
alert(person1.sayName == person2.sayName);//true
動態原型形式
有其他面向對象履歷開闢的職員看到自力的組織函數和原型時,很可能會肥腸疑心,動態原型形式就是處理這個題目的一個計劃。
function Person(name,age){
this.name = name;
this.age = age;
}
if(typeof this.sayName != "function"){
Person.prototype.sayName = function(){
alert(this.name);
};
}
這裏只在sayName()要領不存在的情況下才會將它增加到原型中。這段代碼只會在早期挪用才會實行。
寄生組織函數形式
這個形式能夠在特別的情況下用來為對象建立組織函數。假定我們想建立一個具有分外要領的特別數組。因為不能直接修正Array組織函數,因而能夠運用這個形式。
function SpecialArray(){
var values = new Array();
values.push.apply(values,arguments);
values.toPipedString = function(){
return this.join("|");
};
return values;
}
var colors = new SpecialArray["red","blue","green"];
alert(colors.toPipedString());//red|blue|green
申明:關於寄生組織函數形式,起首返回的對象與組織函數或許與組織函數的原型屬性之間沒有關係;組織函數返回的對象與在組織函數外部建立的對象沒有什麼差別。因而不能依靠instanceof操作符來肯定對象的範例。
穩妥組織函數形式
所謂穩妥對象,指的是沒有大眾屬性,而且其要領也不援用this的對象。穩妥對象最適合在一些平安的環境中(制止運用this和new的環境),或許在防備數據被其他應用程序修改時運用。與寄生組織函數相似的形式;但有兩點差別:1.新建立對象的實例要領不援用this;2.不運用new操作符挪用組織函數;
function Person(name,age){
var o = new Object();
o.sayName = function(){
alert(name);
};
return o;
}
//運用
var friend = Person("liaojin",18);
friend.sayName();//liaojin
如許變量person中保留的是一個穩妥對象,而除了挪用sayName()要領外,沒有別的要領能夠接見其數據成員,縱然有其他代碼會給這個對象增加要領或數據成員,但也不可能有別的方法接見傳入到組織函數中的原始數據,異常適合在某些平安實行環境下運用。
與寄生組織函數形式相似,運用穩妥組織函數形式建立的對象與組織函數之間也沒有什麼關係,因而instanceof操作符對這類對象也沒有什麼意義