简体   繁体   中英

Javascript design approach for inheritance with _.extend

I'm working with a JavaScript application that uses Underscore.js to handle a lot of inheritance. The standard pattern for object definition is one where the basic object is defined in a variable and then its prototype is defined directly afterwards, like this:

var Parent = function()
{
    this.name="parent";
    this.loadData();
};
Parent.prototype = {
    loadData: function() 
    {
         this.say="parent loadData";   
    },
    action: function()
    {
       return this.name+" says: '"+this.say+"'";   
    }

};

This works fine and is reasonably easy to read, but I am a little confused by the way that inheritance is treated in the system. The authors have used the _.extend method to create a child object in the same format, like this:

var Child = function()
{
    this.name="child";
    _.extend(this, new Parent());    

};
Child.prototype= {
    loadData: function()
    {
         this.say="child data loaded";   
    }
});

The problem is that although core properties seem to be copied alright, I appear to have the parent rather than child's methods.

var myParent = new Parent();
var myChild = new Child();
console.log( myParent.action() ); // "parent says: 'parent loadData'"
console.log( myChild.action() );  // "child says: 'parent loadData'"

I tried a _.extend( Child.prototype, { ...etc but that didn't seem to help. Now I could go back to the way I have handled inherited properties in the past Child.prototype.loadData=function() but it would break the idiom used through the rest of the application, so I'm wondering: Is this is a standard approach to JavaScript object orientation? If so does it have a name/some documentation anywhere? Is there a way to keep this model and have practical inheritance working correctly while retaining readable code?

 _.extend(new Parent(), this); 

Urgh! Check the underscore docs on what this does: it creates a new Parent instance and copies the name property (and maybe some inherited ones) to it. Then, it will throw that object away. Why? I don't know.

There is a pattern called parasitic inheritance that works a little like mixins, which at least return s that amended object to become the "child instance". But as it stands, this is totally useless.

What would be acceptable?

_.extend(this, new Parent());

would copy the properties on the actual child instance. But there an even easier solution - just create them on the new instance right away:

Parent.call(this);

I tried a _.extend( Child.prototype, { … but that didn't seem to help.

Well, it was a step in the right direction. Next to that "super" call from above, you also want to have the shared (prototype) properties of the parent on the child's prototype. You can do

_.extend(Child.prototype, Parent.prototype, {
    loadData: …
});

to copy them (and then the new, child-specific properties) onto the prototype object, but the standard solution is to create an object that (dynamically, prototypically) inherits from Parent.prototype :

Child.prototype = _.extend(Object.create(Parent.prototype), {
    loadData: …
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM