Objects don't inherit prototyped functions

inheritance, javascript, oop, prototype

Solution

Seems like `Bla2` didn't inherit it from the `Bla` class!

Right. You haven't done anything to hook up inheritance there, you've just created a member of `Bla2` called `base` which is a `Bla` instance. `base` is not a special identifier in JavaScript.

The typical way to set up inheritance in JavaScript looks like this:

// The base constructor function
function Base(x) {
    // Base per-instance init
    this.x = x;
}

// An example Base function
Base.prototype.foo = function() {
    console.log("I'm Base#foo, x = " + this.x);
};

// The Derived constructor function
function Derived(x, y) {
    // Normally you need to call `Base` as it may have per-instance
    // initialization it needs to do. You need to do it such that
    // within the call, `this` refers to the current `this`, so you
    // use `Function#call` or `Function#apply` as appropriate.
    Base.call(this, x);

    // Derived per-instance init
    this.y = y;
}

// Make the Derived.prototype be a new object backed up by the
// Base.prototype.    
Derived.prototype = Object.create(Base.prototype);

// Fix up the 'constructor' property
Derived.prototype.constructor = Derived;

// Add any Derived functions
Derived.prototype.bar = function() {
    console.log("I'm Derived#bar, x = " + this.x + ", y = " + this.y);
};

...where `Object.create` is from ES5, but it's one of the things that can easily be mostly shimmed. (Or you can use a function that only does the bare minimum without trying to do all of `Object.create`; see below.) And then you use it:

var d = new Derived(4, 2);
d.foo(); // "I'm Base#foo, x = 4"
d.bar(); // "I'm Derived#bar, x = 4, y = 2"

Live example | source

In older code you sometimes see the `Derived.prototype` set up like this instead:

Derived.prototype = new Base();

...but there's a problem with doing it that way: `Base` may do per-instance initialization which isn't appropriate for the entirety of `Derived` to inherit. It may even require arguments (as our `Base` does; what would we pass for `x`?). By instead making `Derived.prototype` just be a new object backed by the `Base.prototype`, we get the correct stuff. Then we call `Base` from within `Derived` to get per-instance init.

The above is very basic and as you can see involves a number of steps. It also does little or nothing to make "supercalls" easy and highly-maintainable. That's why you see so many "inheritance" scripts out there, like Prototype's `Class`, Dean Edwards' Base2, or (cough) my own `Lineage`.

If you can't rely on having ES5 features in your environment, and don't want to include a shim that does the basics of `Object.create`, you can just use this function in its place:

function simpleCreate(proto) {
    function Ctor() {
    }
    ctor.prototype = proto;
    return new Ctor();
}

Then instead of

Derived.prototype = Object.create(Base.prototype);

you'd do:

Derived.prototype = simpleCreate(Base.prototype);

Of course, you can do more to automate hooking things up — which is all `Lineage` basically does.

...and finally: Above I've used anonymous functions for simplicity, e.g.:

Base.prototype.foo = function() {
    // ...
};

...but I don't do that in my real code, because I like to help my tools help me. So I tend to use the module pattern around each "class" (constructor function and associated prototype) and use function declarations (since I do work for the web, and IE7 and IE8 still have problems with named function expressions. So if I weren't using `Lineage`, I'd do the above like this:

// Base
(function(target) {
    // Base constructor
    target.Base = Base;
    function Base(x) {
        // Base per-instance init
        this.x = x;
    }

    // An example Base function
    Base.prototype.foo = Base$foo;
    function Base$foo() {
        console.log("I'm Base#foo, x = " + this.x);
    }
})(window);

// Derived
(function(target, base) {
    // The Derived constructor function
    target.Derived = Derived;
    function Derived(x, y) {
        // Init base
        base.call(this, x);

        // Derived per-instance init
        this.y = y;
    }

    // Make the Derived.prototype be a new object backed up by the
    // Base.prototype.    
    Derived.prototype = Object.create(base.prototype);

    // Fix up the 'constructor' property
    Derived.prototype.constructor = Derived;

    // Add any Derived functions
    Derived.prototype.bar = Derived$bar;
    function Derived$bar() {
        console.log("I'm Derived#bar, x = " + this.x + ", y = " + this.y);
    }
})(window, Base);

...or something like that. Live copy | source

Problem

I have one constructor function, which acts as a superclass: ``` Bla = function(a){this.a = a;} ``` I prototype it to include a simple method: ``` Bla.prototype.f = function(){console.log("f"); ``` And now new `Bla(1).f();` will log "f" in the console. But, lets say that I need a subclass that inherits from Bla: ``` Bla2 = function(a) { this.base = Bla; this.base(); } x = new Bla2(5); ``` Now, as expected, `x.a` gives me `5`. But, `x.f` is `undefined`! Seems like `Bla2` didn't inherit it from the `Bla` class! Why is this happening and how do I correct it?

Original source