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'