7 ms·
How Javascript Prototypal Inheritance Really works
- deleted 15y ago[deleted]
- vjeux 15y agoI just added a note saying that __proto__ is not standard and not supported on IE. Thanks for the comment :)
- city41 15y agogah, I saw that so I tried to quickly delete my comment :) Oh well. The deleted comment above just mentioned __proto__ is not standard.
- masklinn 15y agoThe note should be much bigger. And __proto__ really isn't "supported" anywhere: it's an implementation detail. It's been deprecated in Mozilla, and Opera used not to have it (as recently as 2009, though there is now an __proto__ property on all objects). I would recommend a note similar to Dmitry Soshnikov's in his Javascript: The Core: http://dmitrysoshnikov.com/ecmascript/javascript-the-core/#an-object http://dmitrysoshnikov.com/ecmascript/javascript-the-core/#a... > Let’s take a basic figure of an object with which we will operate in the following descriptions. A prototype of an object is referenced by the internal [[Prototype]] property. However, in figures we will use __<internal-property>__ notation, and in particular for the prototype object: __proto__ (that’s moreover, is a real, but non-standard, implementation in some engines, e.g. SpiderMonkey). It uses __proto__ but makes quite clear that the property is just an implementation detail of the graphs.
- vjeux 15y agoThanks for the comment. I have added big red (orange...) box to make sure that no one uses __proto__ in real code :)
- simonsarris 15y ago__proto__ is also deprecated and Object.getPrototypeOf should be used instead.
- vjeux 15y agoUnfortunately, getPrototypeOf is read only. It does not give an alternative to "new".
- pom 15y agoIt took me a while to get it, especially since the new keyword makes matters really confusing. But after reading about the language Self, I am really using prototypal inheritance, and no more of the "new" business for me.
- munificent 15y agoGot any public code? I'd like to see examples of non-class-style JS code.
- pom 15y agoYou can have a look at: https://github.com/julienq/spqr/blob/master/populus.js https://github.com/julienq/spqr/blob/master/populus.js Bear in mind that it's still a work in progress. Look for "populus.object", especially create(), is_a() and call_super(). There is still something called $new (not new because some picky parsers don't like it) but it's just the chaining of create() (a wrapper around Object.create()) and init().
- joske2 15y agoObject.create is a standard function in ecmascript5. I would add a check such as "if (!Object.create) {Object.create = ... }".
- kordless 15y ago"Error establishing a database connection" No it doesn't.
- kenjackson 15y agoIs the site down?
- vjeux 15y agoThe traffic killed my server. I just rebooted it and activated the wordpress cache. Sorry for the downtime :(
- jashkenas 15y agoI'm sorry to be difficult about this, but ... Like many other Crockford-inspired takes on the subject, vjeux's article is massively bad advice. Firstly, __proto__ is nonstandard, and deprecated. If you write JavaScript that uses it, it won't run in all JS runtimes. Object.create is similarly not available everywhere. It's not available in Firefox < 4, IE < 9, or any version of Opera. Crockford's version of Object.create is not compatible with the native Object.create -- and if you patch it in, you may end up breaking libraries that expect the real thing. But let's say you had it all sorted out, and you had a sane plan for using the native Object.create, and falling back to Crockford's implementation where unavailable ... it's still not a great pattern: http://jsperf.com/object-create-vs-crockford-vs-jorge-vs-constructor/10 http://jsperf.com/object-create-vs-crockford-vs-jorge-vs-con... Running that again today, I see that in Chrome, instantiating objects via Object.create -- either Crockford's or native -- is over 95% slower than using a regular constructor function. We're talking about just creating basic objects here, low-level stuff: how fast you can do it is pretty important if you're aiming for high-performance JavaScript. The prototype property, constructor functions, and "new" are the way that JavaScript objects work, and the way that engines are tuned to optimize JS code. Avoid learning to use them at your own peril.
- raganwald 15y agoI'm with Jeremy on this. Languages all have their own character and way of doing things. Cut with the grain, not against it.
- Autre 15y agoI don't see how Object.create goes against the grain of the lang. On the contrary, `new' was bolt on to make js look like classical oo languages. I have found, in toy and exploratory projects at least, that using variations on Object.create [1] is a nice, strong pattern, that really gets the best out of js. It certainly feels more natural than class based oo. Though, take it with a grain of salt, since I'm unable for now to provide an example backing my thesis :) [1]: https://developer.mozilla.org/en/Differential_inheritance_in_JavaScript https://developer.mozilla.org/en/Differential_inheritance_in...
- glenjamin 15y agoHow about doing it the NodeJS way: https://github.com/joyent/node/blob/master/lib/util.js#L410 https://github.com/joyent/node/blob/master/lib/util.js#L410 This correctly sets this.constructor on instances of any subclass.
- jashkenas 15y ago.. And doesn't work in any browsers or JS engines that don't yet have Object.create, meaning it'll never work in IE < 9. Instead, use a function like this: var inherits = function(child, parent) { var ctor = function(){}; ctor.prototype = parent.prototype; child.prototype = new ctor; ctor.prototype.constructor = child; };
- bobspryn 15y agoI'm not fully following this. Explanation anywhere? Is this how you would do inheritance?
- bobspryn 15y agoSo I found Ashkenas full version of class inheritance in coffescript which simulates what I currently do with multiple crockford creates. In my test case crockford's create is seemingly faster for this, but I'm sure I'm missing something. Someone mind educating me here? http://jsperf.com/js-inheritance-test http://jsperf.com/js-inheritance-test
- insin 15y agoYou don't want to have to actually instantiate an object using the parent constructor in order to get an object with the parent's prototype chain attached for inheritance purposes, as you'd either have to code all constructors which will be inherited from defensively, or pass in dummy arguments to satisfy the constructor when inheriting, which could preclude using a function with no knowledge of the parent constructor such as this one. After calling this function, the child constructor's prototype is an object with no own properties, which itself has the parent's prototype, so references to properties of the parent's prototype will resolve and objects created using the child constructor will return true for "instanceof parent". The other step usually involved, which isn't shown here, is to put `Parent.call(this)` (with any necessary arguments) in the child constructor.
- drblast 15y agoI guess everyone is used to language standards written in a very academic style so they ignore them, but if you really want to know how Javascript works, the ECMAScript specification is clearly written in semi-layman terms and includes a very good explanation of that picture they include at the bottom of the article. http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf http://www.ecma-international.org/publications/files/ECMA-ST...
- richcollins 15y agoThis is faster (don't keep calling new Function) and more OO (send message to prototype to clone it): Proto = { cloneConstructor: new Function, clone: function() { Proto.cloneConstructor.prototype = this; return new Proto.cloneConstructor; } } var Point = Proto.clone(); Point.x = 0; Point.y = 0; Point.print = function() { console.log(this.x, this.y); } var p = Point.clone(); p.x = 10; p.y = 20; p.print(); //10 20