建立物件的方式
- 物件字面量
- 建構函式
- 工廠模式
- 建構函式模式
- 原型模式
- 組合模式
- 動態原型模式
- 寄生建構函式模式
- 穩妥建構函式模式
逐項說明
一、物件字面量
var obj = {};
複製程式碼
例項特性:物件之間相互獨立
- 優勢:程式碼簡潔
- 劣勢:使用同一個介面建立多個物件會產生很多重複程式碼
二、建構函式
var obj = new Object();
複製程式碼
例項特性:物件之間相互獨立
- 優勢:程式碼簡潔
- 劣勢:使用同一個介面建立多個物件會產生很多重複程式碼
三、工廠模式
function createObj(name, list) {
var o = new Object();
o.name = name;
o.list = list;
o.sayName = function() {
alert(this.name);
}
return o;
}
var obj1 = createObj('obj1Name', [1]);
var obj2 = createObj('obj2Name', [1, 2]);
obj2.list.push(3);
console.log(obj1.list, obj2.list); // [1] [1, 2, 3]
console.log(obj1.sayName === obj2.sayName); // false
複製程式碼
例項特徵:物件之間相互獨立,不共享屬性和方法
- 優勢:抽象建立物件的流程
- 劣勢:無法識別物件的型別
四、建構函式模式
function Obj(name, list) {
this.name = name;
this.list = list;
this.sayName = sayName;
}
function sayName() {
alert(this.name);
}
var obj1 = new Obj('obj1Name', [1]);
var obj2 = new Obj('obj2Name', [1, 2]);
obj2.list.push(3);
console.log(obj1.list, obj2.list); // [1] [1, 2, 3]
console.log(obj1.sayName === obj2.sayName); // true
複製程式碼
例項特徵:物件之間相互獨立,但可有共享的方法(全域性中)
- 優勢:避免顯式地建立物件,直接將屬性和方法賦給this物件,避免了return
- 劣勢:全域性作用域下定義多個物件的函式並不合理
建構函式與函式的區別:
建構函式:大寫字母開頭,new操作符呼叫
普通函式:小寫字母開頭,正常呼叫(this物件指向當前作用域所屬的物件)
複製程式碼
使用new操作符建立特定型別的物件:
1. 建立一個新物件
2. 將建構函式的作用域賦給新物件(this指向的新物件)
3. 執行建構函式中的程式碼(新增屬性)
4. 返回新物件
複製程式碼
五、原型模式(所有原生的引用型別均採用此模式建立的)
function Obj() {}
Obj.prototype = {
constructor: Obj,
name: 'obj1Name',
list: [1, 2],
sayName: function() {
alert(this.name);
}
}
var obj1 = new Obj();
var obj2 = new Obj();
obj2.list.push(3);
console.log(obj1.list, obj2.list); // [1, 2, 3] [1, 2, 3]
console.log(obj1.sayName === obj2.sayName); // true
複製程式碼
例項特性:物件間共享屬性和方法,失去獨立性
- 優勢:原型中所有屬性和方法均共享,不必在建構函式中定義物件資訊
- 劣勢:屬性共享造成物件間失去獨立性
六、組合模式(建構函式模式+原型模式,建立自定義型別最常見的方式)
function Obj(name) {
this.name = name;
this.list = [1, 2];
}
Obj.prototype = {
constructor: Obj,
sayName: function() {
alert(this.name);
}
}
var obj1 = new Obj('obj1Name');
var obj2 = new Obj('obj2Name');
obj2.list.push(3);
console.log(obj1.list, obj2.list); // [1, 2] [1, 2, 3]
console.log(obj1.sayName === obj2.sayName); // true
複製程式碼
例項特性:物件間既有共享的方法或屬性,又有獨立的方法或屬性。
- 優勢:利用建構函式模式定義屬性(支援傳參),利用原型模式定義共享的方法和屬性
- 劣勢:每次建立物件都要初始化原型物件,缺乏封裝性
七、動態原型模式(個人認為最佳)
function Obj(name) {
this.name = name;
this.list = [1, 2];
if(typeof this.sayName !== 'function') {
Obj.prototype.sayName = function() {
alert(this.name);
}
}
}
var obj1 = new Obj('obj1Name');
var obj2 = new Obj('obj2Name');
obj2.list.push(3);
console.log(obj1.list, obj2.list); // [1, 2] [1, 2, 3]
console.log(obj1.sayName === obj2.sayName); // true
複製程式碼
例項特性:物件間既有共享的方法或屬性,又有獨立的方法或屬性。
- 優勢:程式碼封裝性較好,同時避免多次初始化原型物件
八、寄生建構函式模式(不推薦)
function Obj(name) {
var o = new Object();
o.name = name;
o.sayName = function() {
alert(this.name);
};
return o;
}
var obj1 = new Obj('obj1Name');
var obj2 = new Obj('obj2Name');
console.log(obj1.sayName === obj2.sayName); // false
console.log(obj1 instanceof Obj); // false
複製程式碼
例項特性:物件間相互獨立,沒有共享方法或屬性
- 優勢:可在特殊情況下為物件建立建構函式(如建立一個具有特殊方法的陣列,由於不能直接修改Array建構函式,則可使用此模式)
- 劣勢:不能通過instanceof來確定物件的型別
九、穩妥建構函式模式(在安全環境下)
function Obj(name) {
var o = new Object();
o.sayName = function() {
alert(name);
}
}
var obj1 = Obj('obj1Name');
obj1.sayName();
複製程式碼
- 優勢:適合在某些安全執行環境中(禁止使用this、new)或防止被其他應用程式改動時使用,只能通過特定的方法訪問屬性。