15

How do I inherit with the Object.create()? I tried these, but none are working:

var B = function() {};
var A = function() {};
A = Object.create(B);
A.prototype.C = function() {};

and

var B = function() {};
var A = function() {};
A.prototype.C = function() {};
A = Object.create(B);

and

var B = function() {};
A = Object.create(B);
var A = function() {};
A.prototype.C = function() {};

Nothing worked. How am I supposed to use this new Object.create()-function?

hippietrail
  • 15,848
  • 18
  • 99
  • 158
Tower
  • 98,741
  • 129
  • 357
  • 507
  • possible duplicate of [Using "Object.create" instead of "new"](http://stackoverflow.com/questions/2709612/using-object-create-instead-of-new) – Bergi Jan 31 '13 at 11:47

7 Answers7

30

There are several ways of doing inheritance in JavaScript

Construction Inheritance. Used if you don't need to call supertype constructor:

function Rectangle(length, width) { 
    this.length = length;
    this.width = width;
}

Rectangle.prototype.getArea = function() {
    return this.length * this.width;
};

// inherits from Rectangle
function Square(size) { 
    this.length = size;
    this.width = size;
}

Square.prototype = Object.create(Rectangle.prototype);

var rect = new Rectangle(6, 8);
var square = new Square(10);

console.log(rect.getArea());                // 48
console.log(square.getArea());              // 100
console.log(rect instanceof Rectangle);     // true
console.log(rect instanceof Object);        // true
console.log(square instanceof Square);      // true
console.log(square instanceof Rectangle);   // true
console.log(square instanceof Object);      // true

Constructor Stealing. Used if need to call supertype constructor:

function Rectangle(length, width) { 
    this.length = length;
    this.width = width;
}

Rectangle.prototype.getArea = function() {
    return this.length * this.width;
};

// inherits from Rectangle
function Square(size) { 
    Rectangle.call(this, size, size);
}

Square.prototype = Object.create(Rectangle.prototype);

var rect = new Rectangle(6, 8);
var square = new Square(10);

console.log(rect.getArea());                // 48
console.log(square.getArea());              // 100
console.log(rect instanceof Rectangle);     // true
console.log(rect instanceof Object);        // true
console.log(square instanceof Square);      // true
console.log(square instanceof Rectangle);   // true
console.log(square instanceof Object);      // true
Vlad Bezden
  • 83,883
  • 25
  • 248
  • 179
22

Object.create() is used to inherit objects, not constructors like you're trying to do. It pretty much creates a new object with the old object set as its prototypal parent.

var A = function() { };
A.prototype.x = 10;
A.prototype.say = function() { alert(this.x) };

var a = new A();
a.say(); //alerts 10

var b = Object.create(a);
b.say(); //alerts 10
b.x = 'hello';
b.say(); //alerts 'hello'

And just to make sure b is not just a clone of a,

a.x = 'goodbye';
delete b.x;
b.say(); //alerts 'goodbye'
Chetan S
  • 23,637
  • 2
  • 63
  • 78
  • Damn, then it does not fit my situation. I need to define a "class" that extends another "class". – Tower Jun 20 '10 at 17:35
  • The point of prototypal inheritance is that you don't have a hard distinction between a "class" and an "object" since a class is an object too. – Kos Dec 09 '11 at 17:12
  • I wish there was `Object.clone(obj)` that would produce the same result as `JSON.parse(JSON.stringify(obj))`. – trusktr Apr 05 '14 at 21:25
  • [there will be](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign), but i wish it were called `Object.clone()`. `Object.assign()` feels odd to me – code_monk Dec 04 '14 at 03:10
  • How will you create another instance of class b inherited from a and: 1. will not change previous instance of b 2. will reuse this code of b in new 10 instances? – Artem A Jun 25 '15 at 12:20
17

The pattern I use for this is to wrap each type in a module, and expose create and prototype properties, like so:

var Vehicle = (function(){
        var exports = {};
        exports.prototype = {};
        exports.prototype.init = function() {
                this.mph = 5;
        };
        exports.prototype.go = function() {
                console.log("Going " + this.mph.toString() + " mph.");
        };

        exports.create = function() {
                var ret = Object.create(exports.prototype);
                ret.init();
                return ret;
        };

        return exports;
})();

Then I can build derived types like so:

var Car = (function () {
        var exports = {};
        exports.prototype = Object.create(Vehicle.prototype);
        exports.prototype.init = function() {
                Vehicle.prototype.init.apply(this, arguments);
                this.wheels = 4;
        };

        exports.create = function() {
                var ret = Object.create(exports.prototype);
                ret.init();
                return ret;
        };

        return exports; 

})();

with this pattern, each type has its own create() function.

Sean McMillan
  • 10,058
  • 6
  • 55
  • 65
  • Followup: These days I use Coffeescript if I feel the need to make class-like things, or an anonymous object if I don't. – Sean McMillan Jan 07 '15 at 19:00
0

The original documentation for Douglas' Object.create is here http://javascript.crockford.com/prototypal.html . Make sure you have included the definition of the the method

if (typeof Object.create !== 'function') {
    Object.create = function (o) {
        function F() {}
        F.prototype = o;
        return new F();
    };
}
  • ..not recommended to use that implementation though, see: http://stackoverflow.com/questions/5199126/javascript-object-create-not-working-in-firefox – zack Jun 14 '11 at 18:47
0

You can define Object.create yourself, but if it is not native you will have to deal with it being enumerated in every for in loop you use for objects.

So far only new webkits- Safari5 and Chrome natively support it.

kennebec
  • 102,654
  • 32
  • 106
  • 127
  • 3
    `Object.create` is a property of `Object`, not of `Object.prototype`, so defining it yourself would not add it to the list of enumerated properties on all objects. – kpozin Mar 13 '12 at 14:29
0

You can find useful information about JavaScript inheritance on Mozilla Development Center.

0

Well it's years late, but for anyone else stumbling upon this. You can use Object.assign in FF and Chrome.

In this example when the Cube is being made with create. First Object.create(this) creates the object with the z property, then with Object.assign(obj, Square.create(x,y)) it will call the Square.create and return and append that into Cube being stored in obj.

 var Square = {
        x: 0,
        y: 0,

        create: function(x,y) {
            var obj = Object.create(this);
            obj.x = x;
            obj.y = y;
            return obj;
        }
    };

 var Cube = {

        z: 0,

        create:function(x,y,z) {
            var obj = Object.create(this);
            Object.assign(obj, Square.create(x,y)); // assign(target,sources...)
            obj.z = z;
            return obj;
        }
    };

// Your code
var MyCube = Cube.create(20,30,40);
console.log(MyCube);