javascript 設計模式

1. 工廠模式(不完美)

工廠模式雖然解決了創建多個相似對象的問題,但卻沒有解決對象識別的問題(即怎樣知道一個對象的類型)。

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('haojie', 28, "Web Developer");

person1.sayName(); // Nicholas
person2.sayName(); // haojie


2. 構造函數模式(不完美)

function Person(name, age, job){
	this.name = name;
	this.age = age;
	this.job = job;
	this.sayName = function(){
		console.log(this.name);
	}
}
var person1 = new Person('Nicholas', 29, 'Software Engineer');
var person2 = new Person('haojie', 28, 'Web Developer');

person1.sayName();
person2.sayName();

其中第5行sayName Function實際等同於
this.sayName = new Function("alert(this.name)");  // 與聲明函數在邏輯上是等價的
每個Person實例都包含一個不同的Function實例,下面的代碼能證明這兩個函數是不相等的
console.log(person1.sayName == person2.sayName); //false
然而,創建兩個完全同樣的任務的Function實例的確沒有必要。


3. 原型模式(不完美)

function Person(){
}

Person.prototype = {
	constructor: Person,
	name: 'Nicholas',
	age: 29,
	job: 'Software Engineer',
	friends: ['Shelby', 'Court'],
	sayName: function(){
		console.log("sayName function say: " + this.name);
	}
}

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

person1.friends.push("Van");

console.log(person1.friends); // "Shelby, Court, Van"
console.log(person2.friends); // "Shelby, Court, Van"
console.log(person1.friends == person2.friends);// true
在此,Person.prototype對象有一個名爲friends的屬性, 該屬性包含一個字符串數組。然後創建了Person的兩個實例。接着,修改了person1.friends引用的數組,想數組中添加了一個字符串。由於friends數組存在於Person.prototype而非person1中,所以剛剛提到的修改也會通過person2.friends(與person1.friends指向同一個數組)反映出來。

4. 組合使用構造函數模式和原型模式(Nicholas 推薦)

// 實例屬性定義在【構造函數】中
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", 29, "Doctor");
		
person1.friends.push("Van");
console.log(person1.friends); // Shelby, Court, Van
console.log(person2.friends); // Shelby, Court
console.log(person1.friends == person2.friends); // false
console.log(person1.sayName == person2.sayName); // true


5. 動態原型模式(Nicholas推薦)

function Person(name, age, job, friends){
	// 屬性
	this.name = name;
	this.age = age;
	this.job = job;
	this.friends = friends;
	
	// 方法
	// 這裏只有在sayName不存在的情況下,纔會將它添加到原型中
	// 也就是new person1的時候會被call到,new person2的時候就不會走這裏了
	if(typeof this.sayName != "function"){
		Person.prototype.sayName = function(){
			console.log(this.name);
		};
	}
}

var person1 = new Person("Nicholas", 29, "Software Engineer", ["Shelby", "Court"]);
var person2 = new Person("haojie", 29, "Software Engineer", ["Shelby", "Court"]);
person1.sayName(); //  Nicholas
person2.sayName(); // haojie

person1.friends.push('Van');
console.log(person1.friends); // Shelby,Court,Van
console.log(person2.friends); // Shelby,Court

console.log(person1.friends == person2.friends); // false
console.log(person1.sayName == person2.sayName); // true

6. 寄生(parasitic)構造函數模式(不推薦)

不能使用person1 instanceof Person 操作符來確定對象類型


7. 穩妥(durable objects)構造函數模式(安全)

function Person(name, age, job, friends){
	// 創建要返回的對象
	var o = new Object();
	
	// 可以在這裏定義私有變量和函數
	
	// 添加方法
	o.sayName = function(){
		console.log(name);
	};
	
	// 返回對象
	return o;
}

var person = Person('Nicholas', 29, 'Software Engineer');
person.sayName(); // Nicholas

console.log(person instanceof Person); // false

這樣,變量person中保存的是一個穩妥對象,而除了調用sayName()方法外,沒有別的方式可以訪問其數據成員。穩妥構造函數提供的這種安全性,使得它非常適合在某些安全執行環境下使用。

與寄生構造函數模式類似,使用穩妥構造函數模式創建的對象與構造函數之間也沒有關係(因爲用的是new Object, 然後return的方法),因此instanceof操作符對這種對象也沒有意義。

發佈了29 篇原創文章 · 獲贊 2 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章