1、工厂模式
- 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程,考虑到在ECMAScript中无法创建类,开发人员就发明了一种函数,用函数来封装以特定接口创建对象的细节,如下面的例子所示。
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("Greg",27,"Doctor");
函数createPerson()能够根据接受的参数来构建一个包含所有必要信息的Person对象。工厂模式虽然解决了创建多个类似对象的问题,但缺没有解决对象识别的问题(即怎样知道一个对象的类型);
2、构造函数模式
function Person(name,age,job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = function() {
alert(this.name)
}
}
var person1 =new Person("Nicholas",29,"Software Engineer");
var person2 =new Person("Greg",27,"Doctor");
与工厂模式不同之处:
- 没有显式地创建对象;
- 直接将属性和方法赋给了this对象;
- 没有return语句;
要创建Person的新实例,必须使用new 操作符。分4步骤:
- 创建一个新对象;
- 将构造函数的作用域赋给新对象(因此this就指向了这个新对象);
- 执行构造函数中的代码(为这个新对象添加属性);
- 返回新对象
3、原型模式
function Person() {
}
Person.prototype.name = "zj";
Person.prototype.age = "29";
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function () {
alert(this.name);
}
var person1 = new Person();
person1.sayName(); //zj
var person2 = new Person();
person2.sayName(); //zj
person2.sayName == person1.sayName //true
person1.name = "greg";
alert(person1.name) //greg --------来自实例
alert(person2.name) //zj --------来自原型
delete person1.name;
alert(person1.name) //zj --------来自原型
我们将sayName()方法和所有属性直接添加到了Person的prototype属性中,构造函数变为了空函数。即使如此,也可以通过调用构造函数来创建新对象。而且新对象还好具有相同的属性和方法。
构造函数模式不同点:
- 新对象的这些属性和方法是由所有实例共享的。换句话说,person1和person2访问的都是同一组属性和同一个sayName()函数。
使用了delete操作符删除了person1.name,之前保存的”gerg“值屏蔽了同名的原型属性。把它删除以后,就恢复了对原型中name属性的连接。
4、组合模式
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",27,"Doctor");
person1.friends.push("Van");
alert(person1.friends) //"Shelby","Court","Van"
alert(person2.friends) //"Shelby","Court"
在这个例子中,实例属性都是在构造函数中定义的,,而由所有实例共享的属性constructor和方法sayName()则是咋原型中定义的。
这种构造函数与原型混成的模式。是目前在ECMAScript中使用最广泛、认同度最高的一种创建自定义类型的方法。
5、动态原型模式
function Person(name,age,job) {
this.name = name;
this.age = age;
this.job = job;
//方法
if(typeof this.sayName != "function") {
Person.prototype.sayName = function () {
alert(this.name)
}
}
}
vvar friend =new Person("Nicholas",29,"Software Engineer");
friend.sayName();
6、寄生构造函数模式
function Person(name,age,job) {
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function () {
alert(this.name)
}
}
vvar friend =new Person("Nicholas",29,"Software Engineer");
friend.sayName(); //'Nicholas'
7、稳妥构造函数模式
function Person(name,age,job) {
var o = new Object();
o.sayName = function () {
alert(this.name)
}
return o;
}
vvar friend =new Person("Nicholas",29,"Software Engineer");
friend.sayName(); //'Nicholas'