Inheritance in JavaScript (2018)

Estimated reading time: 2 minutes.

Coming, as many developers do, from a fairly typical OOP background, I often fall back to architecting applications around the more typical class-based inheritance in use in most languages rather than working with JavaScript's prototype-based inheritance, or writing more functional code.

To that end, I often found myself reusing things like John Resig's Simple JavaScript Inheritance. However, never a fan of nebulous and outwardly changeable references like this in JavaScript, I sought a solution that maintained strong references to the object, allowed access to all the super-class's method as desired, and included provisions for private class variables. This is a basically solved problem, but it doesn't stop us having some fun anyway.

I hacked together the following code. This code doesn't maintain instanceof associations and, at this point in time, I could certainly argue against the entire construct in ways I couldn't have at the time it was written, but that's the joy of learning and growing, isn't it?

My.Object = function() {
    var _public = new Object(), _parent = new Object(), _private = new Object();

    _public.extend = function(parentPublic) {
        if (parentPublic === undefined) parentPublic = _public;
        var newPublic = new Object();
        for (var k in parentPublic)
            newPublic[k] = parentPublic[k];
        newPublic['extend'] = function(usePublic) {
            if (usePublic === undefined)
                usePublic = newPublic;
            return parentPublic.extend(usePublic);
        };
        return {
            _private: new Object(),
            _public: newPublic,
            _parent: parentPublic
        };
    };

    return _public;
};
			

Example Usage

Rather than expect you to attempt to dissect that code, how about you just look at some examples of how it works.

My.Greeter = function() {
    var { _private, _public, _parent } = new My.Object().extend();

    _private.message = "";

    _public.setGreeting = function(message) {
        _private.message = message;
    };

    _public.greet = function() {
        return _private.message;
    };

    return _public;
};

My.NameGreeter = function() {
    var { _private, _public, _parent } = new My.Greeter().extend();

    _private.name = "";

    _public.setName = function(name) {
        _private.name = name;
    };

    _public.greet = function() {
        return _parent.greet() + ", " + _private.name;
    };

    return _public;
};
    			

These objects can then be used:

var nameGreeter = new My.NameGreeter();
nameGreeter.setGreeting('Hello');
nameGreeter.setName('World');
nameGreeter.greet(); // => 'Hello, World'