
How Javascript Prototypal Inheritance Really works - vjeux
http://blog.vjeux.com/2011/javascript/how-prototypal-inheritance-really-works.html
======
jashkenas
I'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-
con...](http://jsperf.com/object-create-vs-crockford-vs-jorge-vs-
constructor/10)

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.

~~~
SeanLuke
???

I'm an old NewtonScript coder -- I wrote a JVM for the Newton, for example.
NewtonScript is a fairly pure proto-OO language, and it was great to work in.
I was thinking of getting into JavaScript, but after reading this article I am
shocked, SHOCKED, at how bad JS appears to be.

Class-style OO has really one major advantage: speed. You can do object slot
lookups in O(1). Otherwise it's mostly disadvantages: it's very wasteful of
memory, it's not dynamic, it mates poorly with functional programming styles,
and its unnecessarily complex.

Let me get this straight. JavaScript is proto underneath (and thus is slow),
but strives so hard to feel like a Class-style OO that it has deprecated
developer access to ITS OWN PROTO OPERATOR. Thus it loses most of the
advantages of proto languages except memory consumption, and still has all of
their disadvantages.

And this nightmarish condition was all done in order to shield the coming-
from-C++ developer from having to "learn" the trivial concept of proto-style
OO? And ten years later it's STILL the case?

~~~
olavk
I think you are conflating static typing with class-based OO. Python for
example is class-based but still fully dynamic. You can mutate classes at
runtime, and even replace the class of an instance at runtime, OTOH Python
cannot do the slot lookup optimization you speak of, due to its dynamical
nature. Python shows that class-based inheritance is very useful (and easy to
use) in a dynamic language.

~~~
SeanLuke
I believe you may have picked the one language which inadvertently illustrates
my point.

My understanding is that Python does these things because it's in the SAME bag
as JavaScript: it's actually a proto language in implementation down deep, but
with a class-based syntax, thus inheriting the disadvantages of both and the
advantages of neither. There's some dynamicism bubbling up from the object
implementation but it's a far cry from the elegance of a real proto language.
I do not know why Guido chose to do this awful thing, but he is at least to be
excused given the age of the language. JavaScript has no such excuse.

~~~
olavk
I guess you could argue that Python is a prototype language deep down because
it performs property lookups at runtime by following a chain of objects.
(Those objects just happen to be classes.) But by that definition, other
dynamic OO languages like Perl or Ruby is also prototype languages.

If you think of classes in Python as a feature build on top of prototypal
inheritance, then it has certainly proved a very useful feature.

~~~
SeanLuke
My understanding is that, unlike Python and JavaScript, Ruby has a true class-
based OO system. Can't speak to Perl.

~~~
olavk
That is interesting, I don't know Ruby that well. But by what definition is
Python not a "true" class based OO-system?

------
drblast
I 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...](http://www.ecma-international.org/publications/files/ECMA-
ST/ECMA-262.pdf)

------
pom
It 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
Got any public code? I'd like to see examples of non-class-style JS code.

~~~
pom
You can have a look at:
<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().

~~~
jashkenas
Holy mother of ...
[https://github.com/julienq/spqr/blob/master/populus.js#L266-...](https://github.com/julienq/spqr/blob/master/populus.js#L266-369)

~~~
pom
If you have more detailed feedback (positive or negative) I'd be happy to hear
it. I'm still figuring this out at the moment.

------
joske2
Object.create is a standard function in ecmascript5. I would add a check such
as "if (!Object.create) {Object.create = ... }".

------
richcollins
This 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

------
glenjamin
How about doing it the NodeJS way:

<https://github.com/joyent/node/blob/master/lib/util.js#L410>

This correctly sets this.constructor on instances of any subclass.

~~~
jashkenas
.. 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
I'm not fully following this. Explanation anywhere? Is this how you would do
inheritance?

~~~
insin
You 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.

------
kenjackson
Is the site down?

~~~
vjeux
The traffic killed my server. I just rebooted it and activated the wordpress
cache. Sorry for the downtime :(

------
kordless
"Error establishing a database connection"

No it doesn't.

