简体   繁体   中英

Object Literals and Prototypal Inheritance?

In javascript, I have an object literal:

var objA = {
  doStuff: function() {
    // do objA stuff
  }
}

I extend objA, and override the doStuff method:

var objB = _.extend(objA, {
  doStuff: function() {
    // do objB stuff
  }
});

However, now when objB.doStuff() is called only objB stuff gets done.

I would like for both objA and objB stuff to be done. I tried the following:

var objB = _.extend(objA, {
  doStuff: function() {
    this.prototype.doStuff.call(this, arguments);
    // do objB stuff
  }
});
objB.__proto__ = objA;

However this doesn't work. I guess I don't understand how prototypal inheritance works when extending object literals. So, what is the right way to do this?

Unserscore's _.extend function doesn't return a new object.

It returns the same object extended, with the new properties. So, your objA has the new doStuff function.

Instead, you may want to use _.clone and then rewrite doStuff on objB .

I would like for both objA and objB stuff to be done.

You have to call the method of objA explicitly:

var objB = _.extend({}, objA, {
  doStuff: function() {
    objA.doStuff.apply(this, arguments);
    // do objB stuff
  }
}, objA);

Note that I'm adding an empty object as first argument, so that first objA 's properties are merged and then yours. For more info about how _.extend works, see the documentation .

Object Literals and Prototypal Inheritance?

Object literals currently don't provide a way to set the prototype. You can create an empty object with a specific prototype with Object.create and then merge other properties into it:

var objB = Object.create(objA);
// `merge` is a fictional function that copies properties from object to another
merge(objB, {
   doStuff: function() { ... }
});

You can still only call objA 's method by explicitly referencing it.


Note: This section probably has to be revised after ES6 is finalized and implement.

In ES6 you will probably be able to set the prototype via the __proto__ property name :

var objB = {
  __proto__: objA,
  doStuff: function() { }
};

or via Object.setPrototypeOf :

var objB = {...};
Object.setPrototypeOf(objB, objA);

Then you should be able to call objA s method via the super keyword:

var objB = {
  __proto__: objA,
  doStuff: function() {
    super.doStuff();
  }
};

What you are doing in your example isn't actually inheritance, but simply creation and modification. To achieve inheritance in Javascript, it's not actually an OBJECT that you are extending, per se. It's a function. An object doesn't provide direct access to its prototype, a function does. So what you're after is likely something more like:

function ObjA() {
    return this;
}
ObjA.prototype.doStuff = function() {
    // do objA stuff
};

function ObjB() {
    return this;
}
ObjB.prototype = new ObjA();
ObjB.prototype.doStuff = function() {
    ObjA.prototype.doStuff.apply(this, arguments);
    // do objB stuff
}

var objA = new ObjA(),
    objB = new ObjB();

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