12 ms·
The world's smallest and fastest classical JavaScript inheritance pattern
- kybernetikos 13y agoWeird. As far as I'm concerned, the smallest classical inheritance pattern in javascript is Subclass.prototype = Object.create(Superclass.prototype); And combined with calling your superclasses constructor in your own constructor, that's it. Two lines at most. You can get a little more complex if you want. In topiarist, I also copy all the 'static' properties from the superconstructor onto the child constructor, check that the prototype hasn't already been modified before replacing it so as to fail fast, and set up the constructor field. But all this stuff is just icing. The smallest classical inheritance pattern is just what I wrote above, and I tend to think that all these articles that make it sound like some deep magic is going on are doing more of a disservice to javascript developers than a service.
- Kiro 13y agoIs that the same as Subclass.prototype = new Superclass()?
- lucio 13y agono, Object.create() creates the object and sets __proto__ but it does not call the function. "new" also calls the function.
- Kiro 13y agoThanks. Would an empty Superclass constructor result in the same thing?
- shawnz 13y agoThat's correct. If the Superclass constructor had code in it, then that code would only be run once, regardless of the number of Subclass objects created. So, they would effectively share their super implementations, as if they were just one object. This doesn't matter when the super constructor doesn't do anything, since there is no difference. The Object.create pattern avoids this by not calling the super constructor at all. If you need the super constructor to be called the way it is in classical inheritance, then you can call Superclass.call(this) in the Subclass constructor along with using Object.create. More details: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create#Classical_inheritance_with_Object.create https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
- deleted 13y ago[deleted]
- camus2 13y agonodejs has the util.inherits function which gives you an extra super_ shortcut to the superclass constructor,it makes sense to use it in node.
- kybernetikos 13y agoQuite right, if you're in node, you may as well use util.inherits, especially since it basically does exactly the same thing (plus super_ and constructor): exports.inherits = function(ctor, superCtor) { ctor.super_ = superCtor; ctor.prototype = Object.create(superCtor.prototype, { constructor: { value: ctor, enumerable: false, writable: true, configurable: true } }); };
- jasonkostempski 13y agoI've been using this pattern for years and never once ran into a problem. Does anyone here have any compelling reason not to?
- kybernetikos 13y agoI've been doing something like this since 2007 on code bases that run into the many hundreds of thousands of lines of code. It is actually the correct way to do classical inheritance in javascript, everything else is trimming, convenience, backwards compatibility or is simply wrong. In fact almost every other 'pattern' out there does this at the heart of it. So, for example you'll see some people use a surrogate instead of doing Object.create (as I did when I first started doing this). That's just doing exactly the same thing as Object.create, but in such a way as to work in pre ecmascript 5 browsers - we didn't have Object.create back then. http://kybernetikos.com/2007/02/07/inheritance-and-javascript/ http://kybernetikos.com/2007/02/07/inheritance-and-javascrip...
- bruceboughton 13y agoIt's interesting that so much time and effort is spent by JavaScript developers implementing classical inheritence when this is a concept increasingly shunned in classically typed languages.
- john_fushi 13y agoIt's shunned in most languages because it's often the only way to do things to offer. OOP is really appropriate in some circumstances but it's not the ultimate paradigm that solves all your problems. Javascript offers some facilities that makes it more polyvalent. Disclaimer : I'm not actually a big fan of javascript.
- Pacabel 13y agoLanguages like C++, Java, C#, Objective-C, Python and Ruby make inheritance dead simple to use. There's one main way of doing it, it's very natural, and so it can often be used excessively. JavaScript makes inheritance a hassle. There are numerous ways of faking it, and they aren't always compatible with one another. I don't think we're seeing inheritance "shunned" in those so-called "classical OO" languages. Given more experience with the potential pitfalls of overuse of inheritance, I do think we're seeing it used less extensively than it once was, but it's still a useful technique. On the other hand, we do see JavaScript developers putting a lot of time and effort into trying to add functionality that is inherently useful, but that isn't offered well by default. It's the opposite of the problem that those other languages suffered from. They make it too easy by default; JavaScript makes it too difficult.
- acjohnson55 13y agoOr maybe not so much too difficult, as pathologically convoluted.
- Tloewald 13y agoI think it's almost like a challenge people do for its own sake because it's something even Crockford failed to do correctly. Write an awesome classical inheritance pattern, write a bunch of tests to convince yourself it works, and then ignore it. Indeed, the fact Crockford's stuff on classical inheritance in The Good Bits was wrong but the book got (and retains) so much traction indicates just how much no-one cares.
- Kiro 13y agoA bit OT and naive question maybe but when do you need OOP in JavaScript? I code a lot of web stuff but the only time I've used OOP in JS is when I make games (where inheritance etc makes sense). Does anyone have a real-world example?
- huskyr 13y agoWhen you're writing an MVC app it might make sense to inherit from something like a Model or a View.
- shacharz 13y agoWhen creating complex apps, by the book design pattern solutions are nice to have, e.g: www.sharefest.me, www.asana.com and so on.
- beefsack 13y agoOOP doesn't necessarily imply inheritance, I use composition quite a lot in JS because it tends to make code much more readable for others. Complex object hierarchies in prototype-based languages can become very confusing very quickly.
- auvrw 13y agohttp://conkeror.org/ http://conkeror.org/
- camus2 13y agoDont worry, once Javascript get classes you'll have all these design pattern talibans on your back saying your code isnt java like / SOLID / DRY / YAGNI / enough. Ironically the PHP community suffers from this problem since it has explicit classes and interfaces,while being a design mess under the hood. About OO and JS, a lot of projects actually use prototypal inheritance , you just dont see it because it's hidden under a jquery like facade/chainable API, where you never need to use the new keyword explicitly. It's obvious that libs that use these kind of DSL are fairly popular in the js world,more than the one using "explicit" OO.
- jashkenas 13y ago> I code a lot of web stuff but the only time > I've used OOP in JS is when I make games That's very doubtful. Ever used a String in JavaScript? Ever used an Array? Ever used a regular expression? How about a function? All of those things are objects in JavaScript — and are used and useful as such. The notion that OOP === single-inheritance needs to be put out of its misery. An object is anything that binds together data and code in a single value, and you use them all the time.
- noiv 13y ago> var bindable = Function.bindable = bind.bind(bind); The latter part of this line needs a bit of documentation.
- jashkenas 13y agoWhile this README is very kindly worded, there are several things to be careful of here: Patching in Object.create with a version that will break third-party code? https://github.com/javascript/augment/blob/master/lib/augment.js#L25-L27 https://github.com/javascript/augment/blob/master/lib/augmen... Extending Object.prototype (!!!) inconsistently between old and new browsers? https://github.com/javascript/augment/blob/master/lib/augment.js#L38-L42 https://github.com/javascript/augment/blob/master/lib/augmen... Just because this is voted to the top of the HN front page ... apparently doesn't mean you don't still need to watch your step. If you'd like a safe, small and fast function for conveniently setting up the prototype chain (a.k.a. classical inheritance in JavaScript), that works cross-browser, try this one on for size: function augment(parent, properties) { var child = properties.constructor || function() { return parent.apply(this, arguments); }; var Surrogate = function(){ this.constructor = child; }; Surrogate.prototype = parent.prototype; child.prototype = new Surrogate; for (var key in properties) { child.prototype[key] = properties[key]; } return child; }; ... the nasty bit of JavaScript-specific business there being the intermediate Surrogate, so that you don't need a concrete instance of the parent class to be instantiated, in order to set your prototype chain. Used like so: var Person = augment(Model, { sortableName: function() { return this.lastName + ', ' + this.firstName; } });
- rubiquity 13y agoI was going to write a reply like this: "Congrats, you just implemented what `extends` does in CoffeeScript!" And then I saw your username. This is still the best implementation of inheritance in JavaScript that I have seen.
- yuchi 13y agoI still don’t understand why no one does `child.__proto__ = parent;` to inherit properties on the constructor chain too.
- nevir 13y agoThere's a bunch of caveats to __proto__: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
- rubiquity 13y agoWait a second. I thought you made a library for classical inheritance in JavaScript. What's all this functional and Array#from crap you're trying to sell with it? Do one thing and do it well. Another thing that sits a little weird with me is that this is in the "javascript" organization on GitHub. I think that's a bit misleading, people might mistake this as some official JS library.
- kemayo 13y agoThis is cool, but I like jashkenas' version in the comments here better. As much as anything, this is because I maintain a reflexive aversion to touching `Object.prototype`. If you're disciplined about avoiding this you can use `for ... in` loops without having to dick around with testing whether the properties are actually directly on your object every time, or writing a wrapper that takes a callback.
- kimjotki2 13y agothis, let's implement inheritance movement nonsense is crufts of Java and C++. (and only C++ can be forgiven, for performance reasons.) Python has proven that a successful dynamic language should have duck-typing, via what called late-binding. you perform lookups on a live object. And this makes even more sense for javascript, which intentionally violates whole notion of typing. In python, yes, there are such things like 'abstract base classes', but they're mostly for convenience, not forced like interfaces in Java. which means no one write codes like: If not isinstance(obj, JavaicMentalMasturbationBase): raise TypeError, "rogue object does not follow holy Javaland commandments: %r" %obj instead, they exist that a framework provider can tell developers, on what are the possible objects that can be fed to their framework. e.g) to use our SessionInterface, your custom session has to provide get_session and save_sesion methods. It seems like Branden Eich's original intention has came to fruition - create a sub-par language and name it after Java. sub-sub-par developers from Java will like the language, it even has closures! But I think he didn't expected Java idiots to force their idioms and harm the whole ecosystem - usually, enterprisey code monkeys were very silent in their cubicles.
- stcredzero 13y agoPython has proven that a successful dynamic language should have duck-typing, via what called late-binding. "Python did that?" asks the Smalltalker.
- coldtea 13y ago>Python has proven that a successful dynamic language should have duck-typing, via what called late-binding. You perform lookups on a live object. It has proven nothing of the short. For one, other languages have done it before (and much better, like Smalltalk). Second, it's not something that, in Python's implementation, makes it particularly suited or pleasant for large codebases. >e.g) to use our SessionInterface, your custom session has to provide get_session and save_sesion methods. So, relegate work that the computer can do to the programmer. Make him do tedious and error-prone housekeeping. The rest of the comment reads like a teenager's attempt at sounding like "cool" and in the know. Things line "JavaicMentalMasturbationBase", "create a sub-par language and name it after Java", "Java idiots" and the like. I assure you that there are Java developers who run circles around whatever your coding skills are. And from your description you don't sound that good at Python either.
- mistercow 13y agoThis is pretty neat. A minor nitpick: >You can easily include it in fiddles and benchmarks using the following HTML code... You really shouldn't use raw.github.com like that. If you're doing something to show a couple of people, or for your own testing, you could use rawgithub.com instead, but otherwise, you should just upload it somewhere reliable.
- alfl23 13y agoJavaScript inheritance library? JS does this by default, no need for more useless boilerplate. The below works in all browsers, IE5 included. function inherits(child, parent) { function tmp() {}; tmp.prototype = parent.prototype; child.prototype = new tmp(); child.prototype.constructor = child; } function A() { this.x_ = 5 }; function B() {A.call(this);};inherits(B, A);
- jwmerrill 13y agoPJs https://github.com/jayferd/pjs https://github.com/jayferd/pjs is the sanest js classical inheritance library I've seen. It's very lightweight, doesn't mess with Object.prototype, and interoperates seamlessly with coffeescript classes.