JS最全創(chuàng)建對象方式匯總
1.最簡單的方式--創(chuàng)建一個Object實例
var person = new Object(); //創(chuàng)建實例
person.name = "BlueBeginner"; //給實例添加屬性
person.age = 21; //添加屬性
person.sayName = function(){ //添加方法
alert(this.name);
}
2.對象字面量
var person = {
name:'BlueBeginner',
age:21,
5:true,
sayName:function(){
alert(this.name);
}
}
以上均為創(chuàng)建單個對象的方法,如果只需要少數(shù)具有不同屬性和方法的對象,以上方法簡單方便,但是當(dāng)我們需要很多具有相似屬性和方法的對象時,使用以上方法顯然不切實際,因為會產(chǎn)生大量的重復(fù)代碼。以下方法,便是為創(chuàng)建一類對象而生。
3.工廠模式
function createPerson(name,age,job){
var o = new Object();//顯式創(chuàng)建對象
o.name = name;
o.age = age;
o.job = job;
o.sayName = function(){
alert(this.name);
}
return o;//返回對象
}
var personone = createPerson("BlueBeginner",21,"web Engineer");
var persontwo = createPerson("DJL",23,"web Engineer");
函數(shù)根據(jù)接受的參數(shù)來創(chuàng)建對應(yīng)的對象,可以無數(shù)次的調(diào)用此函數(shù),每次都會返回一個包含3個屬性1個方法的對象。
工廠模式注意:
- 需要用var顯式地創(chuàng)建對象
- 有return語句,返回對象
- 工廠模式?jīng)]有解決對象的識別問題,我的理解是不能確定對象由哪個函數(shù)創(chuàng)建,看以下代碼
alert(personone instanceof createPerson);//false
alert(personone instanceof Object);//true
4.構(gòu)造函數(shù)模式
function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
alert(this.name);
}
}
var personone = new Person("BlueBeginner",21,"web Engineer");
var persontwo = new Person("DJL",23,"web Engineer");
構(gòu)造函數(shù)模式注意:
- 沒有顯式地創(chuàng)造對象
- 直接將屬性和方法賦值給了this對象
- 沒有return語句
- 構(gòu)造函數(shù)名首字母大寫
- 使用new操作符創(chuàng)建實例
- 創(chuàng)建一個新對象
- 將構(gòu)造函數(shù)的作用域賦給這個對象(因此this指向這個對象)
- 執(zhí)行構(gòu)造函數(shù)中的代碼
- 返回新對象
- 之所以說構(gòu)造函數(shù)解決了工廠模式不能識別對象類型的問題,看下面的代碼
alert(personone instanceof Object);//true
alert(personone instanceof Person);//true
然而無論是工廠模式還是構(gòu)造函數(shù)模式,都存在一個相同的問題,即--不同實例上的同名函數(shù)是不相等的,看以下代碼:
alert(personone.sayName == persontwo.sayName);//false
這樣的話,以上的兩種模式都創(chuàng)建了兩個完成同樣任務(wù)的Function實例,這樣做完全沒必要。而且,對于構(gòu)造函數(shù)模式,因為有this對象在,根本不用在執(zhí)行代碼前就把函數(shù)方法綁定到特定對象上面,大可像下面代碼所示,將方法寫到構(gòu)造函數(shù)外面:
function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = sayName;
}
function sayName(){
alert(this.name);
}
這樣的話,所有實例共享了在全局作用域中定義的函數(shù)方法。但是很顯然的是,如果需要很多很多方法呢?以這種方法,豈不是需要定義很多很多全局函數(shù)?在全局中定義的函數(shù),只能被某些對象調(diào)用,這讓全局作用域有點名不副實。好在,這些問題,可以通過原型模式來解決。
5.原型模式
function Person(){};
Person.prototype.name = "BlueBeginner";
Person.prototype.age = 21;
Person.prototype.job = "web Engineer";
Person.prototype.sayName = function(){
alert(this.name);
};
var personone = new Person();
var persontwo = new Person();
personone.sayName();//'BlueBeginner'
persontwo.sayName();//'BlueBeginner'
alert(personone.sayName == persontwo.sayName);//true
原型模式注意:
- 所有實例共享相同的屬性和方法
- 對于方法和基本屬性值,這樣很合適,但是對于引用類型的值,卻出現(xiàn)了問題。在實例中重寫引用類型的值會修改原型中的同名屬性。如下:
function Person(){};
Person.prototype = {
constructor:Person,
name:'BlueBeginner',
age:21,
friends:['DJL','ZH'],
sayName:function(){
alert(this.name);
}
}
var personone = new Person();
var persontwo = new Person();
personone.friends.push('YR');
alert(personone.friends);//'DJL','ZH','YR'
alert(persontwo.friends);//'DJL','ZH','YR'
alert(personone.friends == persontwo.friends);//true
在第一的實例personone中重寫引用類型值后,第二個實例所得到的原型上的引用類型值也被修改了,這顯然不盡人意。所以很少有人單獨使用原型模式。
關(guān)于原型模式的理解請看
6.組合使用構(gòu)造函數(shù)模式和原型模式
function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.friends = ['DJL','ZH']
}
Person.prototype = {
constructor:Person,
sayName:function(){
alert(this.name);
}
}
var personone = new Person("BlueBeginner",21,"web Engineer");
var persontwo = new Person("DJL",23,"web Engineer");
personone.friends.push('YR');
alert(personone.friends);//'DJL','ZH','YR'
alert(persontwo.friends);//'DJL','ZH'
alert(personone.sayName === persontwo.sayName);//true
alert(personone.friends == persontwo.friends);//false
這種模式將構(gòu)造函數(shù)和原型分開,在構(gòu)造函數(shù)里面寫屬性,在原型里面寫方法,可以說,這是用來定義引用類型的一種默認模式,當(dāng)然,有同學(xué)看到獨立的構(gòu)造函數(shù)和原型時,會感到困惑,下面這個模式,便解決了這個問題。
7.動態(tài)原型模式
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);
};
};
}
這種模式方法確實非常完美,if判斷代碼只會在初次調(diào)用構(gòu)造函數(shù)時才會執(zhí)行,此后,原型已經(jīng)初始化,不需要再做什么修改了。