JS设计模式 - 原型模式与构造函数模式

1,324 阅读3分钟

这是我参与更文挑战的第18天,活动详情查看更文挑战

相关文章内容:

原型模式

原型模式称为基于现有对象的模板通过克隆来创建对象的模式。 我们可以将原型模式视为基于原型继承,在原型继承中我们创建对象作为其他对象的原型。原型对象本身被有效地用作构造函数创建的每个对象的蓝图。

ECMAScript 5标准中定义的真正的原型继承,需要使用Object.create。为了提醒自己,Object.create创建一个具有指定原型的对象,并且还可以包含指定的属性(例如Object.create( prototype, optionalDescriptorObjects ))。

var myCar = {
 
  name: "Ford Escort",
 
  drive: function () {
    console.log( "Weeee. I'm driving!" );
  },
 
  panic: function () {
    console.log( "Wait. How do you stop this thing?" );
  }
 
};
 
// Use Object.create to instantiate a new car
var yourCar = Object.create( myCar );
 
// Now we can see that one is a prototype of the other
console.log( yourCar.name );

Object.create也使我们能够轻松实现高级概念,如差异继承,其中对象能够直接从其他对象继承。我们之前看到,Object.create允许我们使用第二个提供的参数初始化对象属性。例如:

var vehicle = {
  getModel: function () {
    console.log( "The model of this vehicle is.." + this.model );
  }
};
 
var car = Object.create(vehicle, {
 
  "id": {
    value: MY_GLOBAL.nextId(),
    // writable:false, configurable:false by default
    enumerable: true
  },
 
  "model": {
    value: "Ford",
    enumerable: true
  }
 
});

如果我们希望不直接使用原型模式Object.create,我们可以按照上面的例子模拟模式如下:

var vehiclePrototype = {
 
  init: function ( carModel ) {
    this.model = carModel;
  },
 
  getModel: function () {
    console.log( "The model of this vehicle is.." + this.model);
  }
};
 
 
function vehicle( model ) {
 
  function F() {};
  F.prototype = vehiclePrototype;
 
  var f = new F();
 
  f.init( model );
  return f;
 
}
 
var car = vehicle( "Ford Escort" );
car.getModel();

Prototype模式的最后一种替代实现可能如下:

var beget = (function () {
 
    function F() {}
 
    return function ( proto ) {
        F.prototype = proto;
        return new F();
    };
})();

原型模式与构造函数模式

上图中构造函数模式的两种属性,实例属性与共有属性,因为构造函数模式如果没有使用prototype方式的话,我们只能叫做这两个名字,所以为了兼容不适用prototype的方式,这里暂且叫做这两个和名字。至于原型模式的话就是自有属性与从原型链上继承而来的属性。

首先二者的创建对象的方式不同,原型模式必须拥有prototype的存在,而构造函数方式不必依赖prototype。

第二的是谈一下自己对于二者之间的一些理解吧。就好像在日常开发中这个team中有许多的成员,内部也会有小组。所有的成员相对于team来讲的话,那就是构造函数模式,这里team并不是指某一个个体,而是相当于一个function,我们所有的成员因为这个team工作在一起。在日常开发中,team对于我们的限制其实不大,只有当我们面向整个冻死的时候,才会提到我们的共有属性,某一个team。大部分的时间我们还是坐着自己的事情(实例属性)。

然后我上面有一个leader,我们两个一组,现在这个leader,我就是相当于原型模式,现在这个原型对象就是leader,我在这个组里工作就一定会有一些leader定义的工作方式(继承属性),当然也有一些自己处理问题的方式(自有属性)

这个例子可能不太恰当,更多的理解我认为二者的侧重点不同,尽管看起来没有什么区别。构造函数模式侧重于处理多个对象,只是想要说明这些对象一些共同点,但是不会对于个体有很多的限制。原型模式的侧重点应该是处理较少的对象,需要原型对象与实例对象的紧密联系,会对实例对象有着较多的限制。

不管对于构造函数模式的共有属性,还是原型对象的继承属性,实例对象都是可以重写的。