使用Object構(gòu)造函數(shù)和字面量都可以創(chuàng)建對(duì)象 ,但是同一個(gè)接口創(chuàng)建多個(gè)對(duì)象時(shí)候會(huì)產(chǎn)生大量重復(fù)代碼;
//工廠模式
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", 29, "Software Engineer");
var person2 = createPerson("Greg", 27, "Doctor");
構(gòu)函數(shù)模式
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
alert(this.name);
}; }
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");
對(duì)比上面工廠模式,構(gòu)造函數(shù)模式
- 沒有直接new一個(gè)對(duì)象
- 直接把屬性和方法賦值給this
- 有 return語句
要?jiǎng)?chuàng)建Person的新實(shí)例必須使用new關(guān)鍵字,以這種方法調(diào)用構(gòu)造函數(shù)回家里下面四個(gè)步驟
- 創(chuàng)建一個(gè)新對(duì)象
- 將構(gòu)造函數(shù)的作用域賦給新對(duì)象(this指向這個(gè)新對(duì)象)
- 執(zhí)行構(gòu)造函數(shù)中的代碼(添加屬性和方法)
- 換回新對(duì)象
前面例子中person1,person2,分別為Person,的兩個(gè)不同的實(shí)例,這兩個(gè)實(shí)例都有一個(gè)constructor屬性并且這個(gè)屬性指向Person;
alert(person1.constructor == Person); //true
alert(person2.constructor == Person); //true
但是上面的例子中構(gòu)造函數(shù)模式也有問題;實(shí)例化兩次為每個(gè)實(shí)例都創(chuàng)建了一個(gè)sayName方法,這兩個(gè)sayName方法是兩個(gè)不同的對(duì)象,
alert(person1.sayName == person2.sayName); //false
然而這兩個(gè)sayName作用一樣沒必要?jiǎng)?chuàng)建兩個(gè);ECMAScript 中的函數(shù)就是一個(gè)對(duì)象每定義一個(gè)函數(shù)就是實(shí)例化一個(gè)對(duì)象;我們可以嘗試把函數(shù)定義轉(zhuǎn)移到構(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);
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");
這樣他們就是用的同一個(gè)sayName函數(shù);
然而這樣在全局作用域定義的函數(shù)只在某個(gè)對(duì)象中引用,讓這個(gè)全局作用與函數(shù)有點(diǎn)名不副實(shí);并且當(dāng)有多個(gè)方法那在全局作用域則要定義大量函數(shù);
我們可以通過原型模式來解決這個(gè)問題
原型模式
function Person(){
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
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