Object構造函數和對象字面量都可以用來創建單個對象,但是在創建多個對象時,會產生大量重覆代碼. 1.工廠模式 工廠模式抽象了創建具體對象的過程.由於ECMAScript無法創建類,我們用函數來封裝 以特定介面創建對象 的細節. 2.構造函數模式 用來創建特定類型的對象,比如Object/Arr ...
Object構造函數和對象字面量都可以用來創建單個對象,但是在創建多個對象時,會產生大量重覆代碼.
1.工廠模式
工廠模式抽象了創建具體對象的過程.由於ECMAScript無法創建類,我們用函數來封裝以特定介面創建對象的細節.
function createPerson(name, age, job) {
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function() {
console.log(this.name);
}
return o;
}
// 根據接收到的參數,構建一個包含三個屬性一個方法的對象,並返回
var person1 = createPerson("zhu", 26, "FE");
ps. 工廠模式解決了創建多個相似對象的問題,卻無法識別對象(對象的類型)
2.構造函數模式
用來創建特定類型的對象,比如Object/Array這樣的原生構造函數,或者自定義構造函數(可以自定義對象類型的屬性和方法).
/* 1.沒有顯示創建對象
* 2.直接將屬性和方法賦值給this對象
* 3.沒有return語句
* 4.首字母大寫(區別於ECMAScript中其他函數,構造函數本身也是函數,只不過可以創建對象)
*/
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = function() {
console.log(this.name);
}
}
// 必須使用new操作符
var person1 = new Person("zhu", 26, "FE");
var person2 = new Person("liu", 23, "JAVA");
2.1 調用該總種構造函數會經歷四個步驟
- 創建一個新對象
- 將構造函數的作用域賦給新對象(因此this就指向了這個新對象)
- 執行構造函數中的代碼(為這個新對象添加屬性)
- 返回新對象
2.2 對象類型
- person1,person2分別保存著Person的一個不同實例,兩個對象都有constructor(構造函數)屬性指向Person.
js person1.constructor == Person, person2.constructor == Person // true
person1,person2既是Object實例也是Person實例.
// 所有對象均繼承自Object person1 instanceof Object, person1 instanceof Person // true person2 instanceof Object, person2 instanceof Person // true
ps. 創建自定義構造函數意味著可以將它的實例標識為一種特定的類型.
2.3 將構造函數當作函數
構造函數與普通函數的區別在於調用它們的方式不同,只要通過new操作符調用,它就可以作為構造函數.
// 當作構造函數使用,使用new操作符來創建一個新對象.
var person = new Person("zhu", 26, "FE");
person.sayName();
// 作為普通函數調用,屬性和方法都被添加到window對象.
// 在全局作用域中調用一個函數時,this對象總是指向Global對象(在瀏覽器中就是window對象)
Person("zhu", 26, "FE");
window.sayName();
// 使用call()或者apply()在某個特定對象的作用域中調用
var o = new Object();
Person.call(o, "zhu", 26, "FE");
o.sayName();
ps. 構造函數模式定義的構造函數是定義在Global對象中的.
2.4 構造函數的問題
每個方法都要在每個實例上重新創建一遍,person1和person2的同名sayName方法不是同一個function的實例.
ps. ECMAScript的函數是對象,因此每定義一個函數,也就實例化一個對象.即每個Person實例都包含一個不同function實例.
// 邏輯上的構造函數可以這樣定義
function Person(name, age) {
this.name = name;
this.age = age;
this.sayName = new function() {
console.log(this.name);
}
}
沒有必要創建兩個完成同樣任務的function實例,然而將sayName提到全局雖然解決做同一件事的問題,但是實際上只能被某個對象調用,而且可能需要定義很多全局函數(無封裝性).