If you want to be fair, this should be called "the problem with OO programming", and the summary of the problem is that it's complicated and requires that you learn a lot of counterintuitive concepts.
If you want to be fair, this should be called "the problem with OO programming", and the summary of the problem is that it's complicated and requires that you learn a lot of counterintuitive concepts.
The result is a system that is fit for neither paradigm. Trying to do work in either one requires a lot of extremely counter-intuitive lines of code that 'you just have to learn'. Unless you want your code to get bogged down such lines, you end up using libraries that allow you to write something that looks more like either Self or Java.
So, the problem isn't that people haven't bothered to learn 'the right way' to do protoclasses in Javascript. The problem is that 'the right way' is stupid. Either make a real prototype system or a real class system (or both!). But the reason that everyone is so unhappy with the state of things is because it sucks.
AFAIK, Self is the progenitor of prototype-based OO. In Self, the way you create a new object is just `someObject copy`. You can dynamically change its prototype later if you want, too. But in traditional JavaScript, you can't do that. You want an object? You need a constructor. Instead of just cloning a prototype, you have to do the whole `function Foo() { blah blah.prototype = someObject blah blah }; myFoo = new Foo()` rigamarole, and there is no standard way to access an object's prototype.
JavaScript has finally got the equivalent of Self's object creation with Object.create, but that is pretty new — and the actual object system still has the whole wonky prototype/constructor/__proto__ mess behind the scenes.
That said, people using JavaScript should be playing to JavaScript's strengths, or picking a different (if not cross-compiled) platform. It's bizarre that people from fundamentally different programming backgrounds complain about these issues. If you don't like C, don't use C. If you don't like JavaScript, write a native application, or cross-compile. There are options, they're in heavy deployment on several major websites, use them. Then everyone can pick the platform they're most comfortable with.
Prototypes are simply more complicated than classes. They change behavior of objects, whereas classes _define_ behavior of objects. The syntax doesn't help it either.
No, that's an objective statement, on which the creator of the language and some of the greater gurus of it, agree.
>My opinion is that prototypes are simpler than classes.
Not in the way prototypes are implemented in JS.
The creator of the language was apologized lots of times for it's many warts (due to lack of design and time constraints plus limited initial scope for the language), and the greatest of its' gurus had to write a book called "Javascript, THE GOOD PARTS".
Someone who cannot see the flows of Javascript's implementation of prototype inheritance, seriously cannot assess good and bad software design.
Secondly, you appear to be claiming that Crockford offers strong criticism of JS's inheritance model in The Good Parts. If that's what you took away from it, I think you would do well to reread that chapter.
Of course JS's inheritance system is imperfect just like that of pretty much any other language.
Well, he sure is on a very short list of js programmers. Who other can you add? Maybe Resig? Ashkenas?
>Secondly, you appear to be claiming that Crockford offers strong criticism of JS's inheritance model in The Good Parts. If that's what you took away from it, I think you would do well to reread that chapter.
No, I'm saying that Crockford doesn't like the way prototypal inheritance is implemented/exposed in javascript --not that prototypal inheritance is inherently bad. He even writes that the basic action of getting prototypal inheritance is not first-class in js:
"In a prototypal system, objects inherit from objects. JavaScript, however, lacks an operator that performs that operation."
And in order to use prototypal inheritance he has written a wrapper function to hide all the inheritance boilerplace correctly. (As has every other js programmer I know of, using several patterns).
Only if you try to make them act like classes.
[citation needed]
I'd argue the opposite: "Prototypes are simply more _intuitive_ than classes."
OO-design says that X is-a Y is-a Z, with inheritance providing the main form of structure.
Prototypical-design says that X is-like-a Y, but with these differences. This NPC (specific, X) is like any other NPC (general, perhaps the original NPC prototype), but with the name Fred and this custom AI code.
They're different ways of thinking, but prototypes are certainly not more complicated than classes in the general case.
----
As for the syntax, though, I totally agree with you.
In prototype-based OO, a constructor is just a function that builds an object. If you like, you can give that function a starting point for building its objects (the prototype), but in the end, it's just a function that builds an object. It's conceptually not that similar to a class in classical OO, even though you can use it to implement classical inheritance.
And that's really the core of the problem: read any book about JavaScript, and the first thing they'll probably tell you after introducing prototypes is how to get something like classical inheritance hierarchies by chaining prototypes together. So people end up thinking "what a strange and roundabout way to handle classes", when the problem is that they shouldn't be thinking about classes in the first place.
And here's the elephant in the room: long prototype chains are not usually the right solution because long inheritance chains in general are not usually the right solution. Classical inheritance just makes it so easy to build elaborate and beautiful hierarchies that most people never realize that doing so is usually just adding complexity for no real gain.
In prototype-based OO, a constructor is just a function that builds an object.
If you like, you can give that function a starting point for building its objects
(the prototype), but in the end, it's just a function that builds an object.
Isn't this called pseudo-classical inheritance?In purely prototypical inheritance one object inherits from another object, there is no need for constructors whatsoever, instead you are just setting __proto__ link so that it points to the object from which you want to inherit.
This way you have much more freedom - you could add initializer method that sets up variables in a similar fashion to constructor, but you could also easily implement singleton or mixin patterns.
Ideally, prototypical inheritance would be done like in the code below, but I doubt we will ever see this supported by JS:
obj1 = {
__proto__: Object.prototype,
init: function() {
}
}
obj2 = {
__proto__: obj1,
init: function() {
super.init()
}
}
obj3 = {}
obj3.__proto__ = obj2
obj3.init()Classical inheritance IS easier to understand compared to how prototypical inheritance was implemented in Javascript --and it's obvious from the examples he gives, and all the workarounds to use prototypical inheritance correctly in all the major JS frameworks.
The implementation details of prototype inheritance should not leak to the language, but in JS, they do.