[1]: https://developer.mozilla.org/en/Differential_inheritance_in...
[1]: https://developer.mozilla.org/en/Differential_inheritance_in...
I've had this debate with folks many times before, and literally every time it comes up, they're unable to find an example of using prototypal inheritance in a style that wouldn't also be considered classical.
If you think that writing:
var point = Object.create(Point);
... is somehow magically prototypal, while writing: var point = new Point;
... is unnaturally classical, I'll argue that you're missing the, ahem, point.They're two different ways of writing the exact same pattern. And, if we're being honest with ourselves, the "Point" object in that code should rightly be called a "class": it's the abstract object that defines the shape of all points. Of course, in JavaScript, we also tend to call it the "constructor function" (which it is, technically), and sometimes, the "prototype" (because it serves in that role).
Prototypal inheritance makes a difference if one instance inherits field values (other than functions) from another instance. But this does not seem to be very common.
I believe one of the original use cases for prototypal inheritance were to save memory by letting GUI controls share common properties. Eg. if you had 10 buttons on the screen which all had the same color, same dimensions etc. With class based inheritance each instance would have their own copy of all properties, even if they have the same values in each instance.
I don't think that kind of optimization is relevant in modern JavaScript.
What is no mistake is the refreshing change of view you get when you start embracing objects and prototypal inheritance. See for example the traits library[1, 2].
[3]: Is a cursory introduction to Self, with another points example :)
[4] Contains an example of my own (heavily inspired by Self and Io). I have stitched together various internet sources to come up with `clone', an operator assisting in differential inheritance.
[1]: http://traitsjs.org/
[2]: http://code.google.com/p/es-lab/source/browse/trunk/src/trai...
A factory is very different from a keyword baked into the language. The new keyword suggests that the underlying language is doing the construction, and all of the details about the object being created are encoded in its blueprint, "Point."
I consider a factory and a keyword to be two very different patterns regardless of whether you want to call them class-based or prototype-based.
Aside from the simplicity argument, I didn't see anything in Markus's presentation that showed an advantage of prototypes. His point example is cloning a point and then immediately replacing all of the state, so there's nothing there that classes couldn't do (in less code).
Your gist (especially the color point) is an example of using prototypes in a way that's hard with classes. Fortunately, adding classes to JS won't hurt that at all. You could just as easily do:
class Point {
constructor(x, y) {
public x = x;
public y = y;
}
add(other) {
return new Point(this.x + other.x, this.y + other.y);
}
}
let p1 = new Point(0, 0);
let p2 = p1.clone({
color: '#green',
toString: function() {
return this.color + ': ' + uber(this).toString();
},
})
In other words, adding classes to JS won't take away anything already there. It just gets a really common pattern and makes it much less verbose. The idea is to pave the common path of class-like inheritance, but not to build a fence around it to keep you in.