批判我的原型继承模式

Critique my prototypal inheritance pattern

我决定使用 Object.create,因为它看起来比使用 'new' 并且必须为每个函数编写 Car.prototype.func1 = function(){} 更直观, 例如;好像有点太干了。

我顿悟了使用 $.extend 来扩充属性和函数,这使得从我想使用的任何对象中获取代码变得更加容易。一旦对象被扩展,我就使用 Object.create() 来设置原型,所以这些函数对所有实例都是通用的,并将属性作为第二个参数传递。

下面的模式可以吗? jsfiddle

// props use Object.defineProperties() format; can configure each prop as writable, enumerable, etc

var Vehicle = {
    props : { 'colour' : {value:'black'}, 'wheels' : {value:4} },
    proto : { 'drive' : function(){console.log('drive ' + this.colour + ' ' +     this.wheels);} }
};

var Ferrari = {
    props : { 'colour' : {value:'red'}, 'seats' : {value:2} },
    proto : { 'fast' : function(){console.log('ferrari power ' + this.colour + ' ' + this.wheels + ' ' + this.seats);} }
}; 

function init(){

    // copy Vehicle object, so it remains untouched
    var vehicle = $.extend(true,{}, Vehicle); 

    // augment vehicle super-class with sub-class
    $.extend(vehicle.props, Ferrari.props);
    $.extend(vehicle.proto, Ferrari.proto);

    // prototypal inheritance
    var ferrari = Object.create(vehicle.proto, vehicle.props);
    ferrari.drive();
    ferrari.fast();
}

init();

编辑:我放弃了这个想法,太乱了;我正在使用原型模式,显示在 this article.

的末尾

这是创造性的代码,但感觉很混乱,并且引入了太多附带的复杂性,例如需要 jQuery(如果您的项目已经依赖于 jQuery,这未必是件坏事). JavaScript具体是基于原型继承设计的...为什么不利用它呢?

此外,关于您对添加原型属性似乎过于重复的感觉:

var Cat = function() { ... };

// then when defining the prototype...

Cat.prototype.purr = function() { ... };
Cat.prototype.meow = function() { ... };

您会发现出于多种原因(相对于我将在下面展示的方法),人们通常推荐使用上述定义原型属性的方法,原因之一是关于垃圾收集和消除循环引用。但是,如果您担心 "repeating yourself" 太多,只需将原型设置为普通对象即可:

Cat.prototype = {
  purr: purr,
  meow: meow
};

function purr() {
  // whatever
}

function meow() {
  // whatever
}

第二种方法,如上所示,利用了JavaScript的函数提升并引入了类似于the revealing module pattern的概念。

您不应该使用 $.extend 进行继承,您应该在 class 的定义中立即声明继承,而不是稍后在 init 函数中声明继承。
另外,您的“增强型车辆超级-class 与子class”似乎真的很倒退。需要“复制 Vehicle 对象,因此它保持不变”并且您正在从 vehicle 而不是从 [= 创建 ferrari 实例来强调这一点16=].

我建议使用两个辅助函数:

function inherit(superClass, props, proto) {
    return {
        props: $.extend(Object.create(superClass.props), props),
        proto: $.extend(Object.create(superClass.proto), proto)
    };
}
function create(template) {
    return Object.create(template.proto, template.props);
}

你可以像这样使用

var Vehicle = {
    props : { 'colour' : {value:'black'}, 'wheels' : {value:4} },
    proto : { 'drive' : function(){console.log('drive ' + this.colour + ' ' +     this.wheels);} }
};

var Ferrari = inherit(Vehicle, {
    'colour' : {value:'red'},
    'seats' : {value:2}
}, {
    'fast' : function(){console.log('ferrari power ' + this.colour + ' ' + this.wheels + ' ' + this.seats);}
});

var ferrari = create(Ferrari);
ferrari.drive();
ferrari.fast();

除了这些问题,你的模式还不错。使用纯原型继承是一种既定的模式。您可以通过向模板对象 (classes) 添加初始化函数来修改它,例如命名为.constructor,您又回到了典型 class 模式的力量。