Critique my prototypal inheritance pattern [closed]

冷暖自知 提交于 2019-12-13 22:31:01

问题


I've decided to use Object.create, as it seems much more intuitive than using 'new' and having to write Car.prototype.func1 = function(){} for each function, for example; seems a bit too DRY.

I had an epiphany of using $.extend to augment properties and functions, making it easier to grab code from any object I wanted to use. Once the object's extended, I then use Object.create() to set the prototype, so the functions are common to all instances and pass in the properties as the second parameter.

Is the following pattern okay? 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();

Edit : I've abandoned this idea, too messy; I'm using a prototypal pattern, shown at the end of this article.


回答1:


You should not use $.extend for inheritance, and you should declare the inheritance right away at the definition of your class, not somewhen later in an init function.
Also your "augment vehicle super-class with sub-class" seems really backwards. This is emphasized by the need to "copy Vehicle object, so it remains untouched" and that you are creating your ferrari instance from vehicle, not from Ferrari.

I'd recommend to use two helper functions:

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

Which you could use like

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

Apart from these problems, your pattern is quite fine. Using pure prototype inheritance is an established pattern. You may amend it by adding an initialisation function to your template objects (classes), named e.g. .constructor, and you're back at the power of the typical class pattern.




回答2:


It's creative code, but it feels obfuscated and introduces too much incidental complexity, such as the need for jQuery (which isn't necessarily a bad thing if your project already depends on jQuery). JavaScript specifically is designed based on prototypal inheritance... why not take advantage of it?

Also, regarding your feeling about adding prototype properties seeming too repetitive:

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

// then when defining the prototype...

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

You'll find that people usually recommend the above approach of defining prototype properties for several reasons (versus the approach I'm about to show below) because, for one, regarding garbage collection and elimination of circular references. However, if you're worried about "repeating yourself" too much, just set the prototype as a plain object:

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

function purr() {
  // whatever
}

function meow() {
  // whatever
}

The second way of doing it, as shown above, takes advantage of JavaScript's function hoisting and introduces a concept similar to the revealing module pattern.



来源:https://stackoverflow.com/questions/32002843/critique-my-prototypal-inheritance-pattern

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!