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'