一、對象表示方法
1、普通對象
var person=new Object();
person.name="Nicholas";
person.age=19;
person.jog="Software Engineer,";
person.sayName=function(){
alert(this.name);
}
2、對象字面量
var person={
name:"Nicholas";
age:19;
job:"Software Enginner";
sayName:function(){alert(this.name)};
}
二、創建對象
工廠模式
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("Nicholas",19,"SoftEngineer");
var person2=createPerson("Greg",17,"Doctor");
工廠模式:根據外界給定的原料,生產出不同的類型的相應的產品、對象。工廠類負責創建的對象較少,客戶指知道傳入工廠類的參數,
對於如何創建對象(邏輯)不關心。解決了創建多個相似對象的問題。
工廠模式雖然解決了創建多個相似對象的問題,但卻沒有解決對象識別的問題(即怎樣知道一個對象的類型)。構造函數模式
function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
this.sayName=function(){ //等於new Function(){} ,不同實例上的同名函數是不相等的
alert(this.name);
}
}
var Person1=new Person("Nicholas",19,"SoftEngineer");
var Person2=new Person("Greg",17,"Doctor"); //Person1和Person2分別保存着Person的一個不同的實例,這兩個對象的constructor屬性都指向Person
alert(Person1.constructor==Person); //true
alert(Person2.constructor==Person); //true
Person中的代碼
①沒有顯示的創建對象;
②直接將屬性和方法賦給了this對象;
③沒有return語句。
按照慣例,構造函數首字母大寫,非構造函數首字母小寫。
創建自定義的構造函數意味着可以將它的實例作爲一種特定的類型,這是構造函數模式勝過工廠模式的地方。
構造函數的主要問題,就是每個方法都要在每個實例上重新創建一遍。
我們將sayName設置成全局函數
function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
}<pre name="code" class="javascript">Person.sayName=function(){ //等於new Function(){} ,不同實例上的同名函數是不相等的
alert(this.name);
}
var Person1=new Person("Nicholas",19,"SoftEngineer");var Person2=new Person("Greg",17,"Doctor"); //Person1和Person2分別保存着Person的一個不同的實例,這兩個對象的constructor屬性都指向Personalert(Person1.constructor==Person); //truealert(Person2.constructor==Person); //true
可是問題又來了,在全局作用域中定義了一個實際指向讓Person使用的函數,在全局作用域中定義許多僅供特定對象使用的方法,浪費空間而且失去了面向對象的封裝性。因此可以通過原型來解決這個問題。
原型模式
function Person(){
}
Person.prototype.name="Nicholas";
Person.prototype.age=19';
Person.prototype.job="Software Engineer";
Person.prototype.sayName=function(){
alert(this.name);
}
var person1=new Person();
person1.sayName(); //Nicholas
var person2=new Person();
person2.sayName(); //Nicholas
alert(person1.sayName==person2.sayName); //true
原型函數省略了構造函數傳遞初始化參數這一環節,結果所有實例在默認情況下都取得了相同的屬性值。原型模式的最大問題在於共享的本性,由於共享,因此如果一個實例修改了引用,另一個也隨之更改了引用。因此我們通常不單獨使用原型。
雖然可以通過對象實例訪問保存在原型中的值,但卻不能通過對象實例重寫原型中的值。如果我們在實例中創建一個與實例原型相同名稱的屬性,則會將原型中的同名屬性屏蔽。
重寫原型對象會切斷現有原型與之前已經存在的對象實例之間的聯繫,它們引用的仍然是最初的原型。
組合使用構造函數模式和原型模式(重點)
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("Nicholas",29,"Software Engineer");
var person2=new Person("Greg",27,"Doctor");
person1.friends.push("Van");
alert(person1.friends);
alert(person2.friends);
alert(person1.friends==person2.friends); //false
alert(person1.sayName==person2.sayName); //true
混合模式中構造函數適用於定義實例屬性,而原型模式用於定義方法和共享屬性。每個實例都會有自己的一份實例屬性,但同時又共享着方法,最大限度的節省了內存。另外這種模式還支持傳遞初始參數。
動態原型模式
function person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
if(typeof this.sayName!="function"){
person.prototype.sayName=function(){
console.log(this.name);
}
}
}
var friend=new person("Nicholas",28,"Software Engineer");
friend.sayName();
這段代碼只會在初次調用構造函數時執行。此後,原型已經完成初始化,不需要再做什麼修改了。使用動態原型模式時,不能使用對象字面量重寫原型。在已經創建了實例的情況下重寫原型,就會切斷現有實例與新原型之間的聯繫。
寄生構造函數模式
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 friend=new Person("Nicholas",28,"Software Engineer");
friend.sayName(); //"Nicholas"
這個模式可以在特殊的情況下來用來爲對象創建構造函數。(good)
funtion specialArray(){
var values=new Array();
values.push.apply(values,arguments);
values.toPipedString=function(){
return this.join("|");
}
}
var colors=new specialArray("red","blue","green");
alert(colors.toPipedString());
在使用其他模式的情況下,不要使用這種模式。穩妥構造函數模式
所謂穩妥對象,指的是沒有公共屬性,而且其方法也不引用this的對象。
穩妥構造函數模式與工廠模式的區別:
//穩妥構造函數
function person(name,age,sex){
var o=new Object();
o.name=name;
o.age=age;
o.sex=sex;
o.sayName=function(){
console.log(name);
}
return o;
}
var girl=person("zsn",18,"F");
girl.sayName();//zsn
girl.name="hello world";
girl.sayName();//zsn
console.log(girl.name); //hello world
// 工廠模式
function person(name,age,sex){
var o=new Object();
o.name=name;
o.age=age;
o.sex=sex;
o.sayName=function(){
console.log(this.name);
}
return o;
}
var girl=person("zsn",18,"F");
girl.sayName();//zsn
girl.name="hello world";
girl.sayName();//hello world
console.log(girl.name); //hello world
區別就是工廠模式有this,穩妥構造函數沒有this。結果呢,工廠函數的sayName方法調用的值會改變。三、繼承
PS:
1、以new 操作符調用構造函數會經歷一下四個步驟:
創建一個新的對象;
將構造函數的作用域賦給新的對象(因此this就指向了這個新對象);
執行構造函數中的代碼;
返回新對象。