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操作符对这种对象也没有意义。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值