JavaScript創建對象的幾種模式


看《JavaScript高級程序設計》做的一些筆記

工廠模式:

function createPerson(arguments){
	var o = new Object();
	o.name = name;
	o.age = age;
	o.sayName = function(){};
	return o;
}


var person1 = createPerson(arguments);

解決創建多個相似對象的問題


缺點:
沒有解決對象識別問題




構造函數模式:

function Person(arguments){
	this.name = name;
	this.age = age;
	this.sayName = function(){};
}


var person1 = new Person(arguments);
var person2 = new Person(arguments);

構造函數名大寫字母開頭
person1有constructor(構造函數)屬性,指向Person
person1.constructor == Person  //true
person1 instanceof Object  //true
person1 instanceof Person  //true
構造函數當做普通函數使用,屬性和方法都添加給window


缺點:
每個方法在每個實例上都要重新創建一遍
person1.sayName == person2.sayName  //false



原型模式:

每個函數都有一個prototype屬性,指向一個對象,這個對象可以包含特定類型所有實例共享的屬性和方法
function Person(){
}


Person.prototype.name = 'myName';
Person.prototype.age = 66;
Person.prototype.sayName = function(){};


var person1 = new Person();
var person2 = new Person();
person1.name == person2.name  //myName


可以通過對象實例訪問原型中的值,但不能通過對象實例重寫原型中的值
person1.name = 'newName';
person1.name  //newName(來自實例)
person2.name  //myName (來自原型)
訪問屬性時,若沒有在實例中搜索到該屬性,就會在原型中搜索並返回該屬性
使用delete可以刪除實例中的屬性,此時再訪問該屬性則會返回原型中的屬性
delete person1.name;
person1.name  //myName (來自原型)


原型與in操作符:
通過對象能夠訪問屬性時返回true(for-in返回能夠通過對象訪問的、可枚舉的屬性),無論是在實例中還是原型中


原型模式的一些方法:
isPrototypeOf()

Person.prototype.isPrototypeOf(person1)  //true


Object.getPrototypeOf() 返回[[Prototype]]的值
Object.getPrototypeOf(person1) == Person.prototype  //true
Object.getPrototypeOf(person1.name)  //myName


hasOwnProperty() 檢測一個屬性是否存在於實例中

person1.name = 'newName';
person1.hasOwnProperty('name');  //true
person2.hasOwnProperty('name');  //false


hasPrototypeProperty() 檢測一個屬性是否來自原型

hasPrototypeProperty(person1,'name');  //false
hasPrototypeProperty(person2,'name');  //true


Object.keys() 取得對象上所有可枚舉的實例屬性


Object.getOwnPropertyNames() 獲取所有實例屬性,無論是否可枚舉



原型的對象字面量寫法
function Person(){
}
Person.prototype = {
	name:'myName',
	age:66,
	sayName:function(){}
};


這種寫法的constructor屬性不再指向Person,而是指向Object構造函數
var person3 = new Person();
person3 instanceof Person  //true
person3 instanceof Object  //true
person3.constructor == Person  //false
person3.constructor == Object  //true


缺點:
由於其共享的特性,對於包含引用類型值的屬性,實例無法有屬於自己的屬性
例如屬性中包含數組,若通過實例對象對數組進行修改,由於數組存在於prototype中,則會影響到所有的實例。



組合使用構造函數模式和原型模式(廣泛使用):

構造函數模式定義實例屬性,原型模式用於定義方法和共享的屬性
function Person(arguments){
	this.name = name;
	this.age = age;
	this.friends = ['a','b'];
}


Person.prototype = {
	constructor:Person,
	sayName:function(){}
};





動態原型模式:

function Person(arguments){
	//屬性
	this.name = name;
	this.age = age;
	
	//方法
	if(typeof this.sayName != 'function'){
		Person.prototype.sayName = function(){};
		Person.prototype.otherFunction = function(){};
	}
}





寄生構造函數模式:

function Person(arguments){
	var o = new Object();
	o.name = name;
	o.age = age;
	o.sayName = function(){};
	return o;
}




var person1 = new Person(arguments);
除了使用new和構造函數,這個模式跟工廠模式是一樣的


例如要創建一個具有額外功能的Array,由於不能直接修改Array,可以這樣:
function SpecialArray(){
	var sa = new Array();
	sa.push.apply(sa,arguments);  //使用apply是因爲push如果接收數組作爲參數,會將整個數組當做一個元素push
	sa.newFunction = function(){};
}


var arr = new SpecialArray(arguments);
arr.newFunction();





穩妥構造函數模式(安全性考慮):

function Person(name,age){
	var o = new Object();
	o.sayName = function(){
		return name;
	}
	return o;
}


var person1 = Person(name,age);
person1.sayName();  //除了使用sayName()方法之外沒其他辦法訪問到name的值



參考:《JavaScript高級程序設計》(第3版)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章