Question

I have been playing around with Object.create in the EcmaScript 5 spec, and I am trying to create a multiple inheritance type structure.

Say I have a few functions: a, b, and c. With only dealing with prototypes, I can do this:

function a () {}
a.prototype = {
    fnA = function () {},
    propA = 500
};

function b () {}
b.prototype = a.prototype;
b.prototype.fnB = function () {};
b.prototype.propB = 300;

function c () {}
c.prototype = b.prototype;
c.prototype.fnC = function () {};
c.prototype.propC = 200;

But using Object.create, I would do something this:

function a() {}
a.prototype = {
    fnA = function () {},
    propA = 500
};

var b = Object.create(new a());
b.fnB = function () {};
b.propB = 300;

var c = Object.create(b);
c.fnC = function () {};
c.propC = 200;

I think I get the same result both ways.

This seems kinda clunky, because I get on object back instead of a constructor function. It seems to me that doing the regular prototypical inheritance is less intrusive and makes more sense for modular applications that don't need any special treatment to work.

Am I missing anything? Is there any benefit of trying to make Object.create with making constructors? Or is this only useful for copying existing objects? I only want access to properties & functions attached to the prototype, and not functions and properties added afterward to the object.

Or what about this (or use a better deep-copy, but the idea remains the same)?

function A () {}
A.prototype = {
    fn: function () {
        console.log(this.propA + 30);
    },
    propA: 20
};

function B () {}
Object.keys(A.prototype).forEach(function (item) {
    B.prototype[item] = A.prototype[item];
});
B.prototype.propA = 40;

function C () {}
Object.keys(B.prototype).forEach(function (item) {
    C.prototype[item] = B.prototype[item];
});
C.prototype.fn = function () {
    console.log(this.propA + 3);
};


var a = new A(),
    b = new B(),
    c = new C();

a.fn();
b.fn();
c.fn();
Was it helpful?

Solution

Actually you don't get the same result both ways. Consider this line:

b.prototype = a.prototype;

What this is doing is setting b.prototype to exactly the same object reference as a.prototype. If you alter the first object (say by adding a fnB method) you will also alter the second object. They are the same thing. At the end of your first set of code you will have three prototypes that are all exactly the same, with the same methods and properties.

The whole point of prototypal inheritance is that you define an "interesting" object (that is, with all the behavior you want) and then clone it with Object.create and modify the clones to suit your needs (usually by modifying its properties, not its methods).

So suppose you have an adder object:

var adder = {x: 0, y: 0};
adder.execute = function () {
  return this.x + this.y;
}

Then you create a clone and set its properties:

var myadder = Object.create(adder);
myadder.x = 1;
myadder.y = 2;
console.log(myadder.execute()); // 3

Now obviously this is a silly example, but is shows that you can think of prototypal inheritance without having to write constructors and explicit prototypes on those constructors.

OTHER TIPS

If you need to support browsers that don't support Object.create() you can use this

function object(o) {
    function F() {}
    F.prototype = o;
    return new F();
}

The object function untangles JavaScript's constructor pattern, achieving true prototypal inheritance. It takes an old object as a parameter and returns an empty new object that inherits from the old one. If we attempt to obtain a member from the new object, and it lacks that key, then the old object will supply the member. Objects inherit from objects. What could be more object oriented than that?

More can be read here : Prototypal Inheritance in JavaScript

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top