天天看点

JS中 (工厂模式、构造函数模式、原型模式、组合模式、动态原型模式、寄生构造函数模式、稳妥构造函数模式)

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");
           

与工厂模式不同之处:

  1. 没有显式地创建对象;
  2. 直接将属性和方法赋给了this对象;
  3. 没有return语句;

要创建Person的新实例,必须使用new 操作符。分4步骤:

  1. 创建一个新对象;
  2. 将构造函数的作用域赋给新对象(因此this就指向了这个新对象);
  3. 执行构造函数中的代码(为这个新对象添加属性);
  4. 返回新对象

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'
           

继续阅读