Any of you who has used OOP in any “traditional” language, such as C++, Java or PHP and then tried to apply the stuff you know in JavaScript probably know that… things just don’t work like you’re used to.
But what are the things that actually are causing the confusion and how to avoid the problems?
No obvious way of making a class
JavaScript has no class statement and there is more than one way you can create new objects. For example…
function MyClass() { //private stuff var privateVar = 'foo'; function privateFunction() { } //public stuff this.methodName = function(param) { alert(param); } this.variableName = 'hello'; } //or this, also known as "Module pattern" [1] var MyOtherClass = function() { //private stuff var privateVar = 'foo'; function privateFunction() { } return { //public stuff methodName: function(param) { alert(param); }, variableName: 'hello' }; }(); |
[1] YUI Blog JS module pattern
This is just two ways, and I’m sure there are more. Personally I’m using the module pattern method, which is very good as you can have both private and public members with ease.
There’s one thing to note here: Although JS doesn’t actually do anything if you do “class something { }”, the word “class” is still a reserved word in some browsers (such as IE), and therefore you should not use class as a name for a function or a variable.
Member scope
A problem introduced by how JavaScript handles the private member scope. As JavaScript does not really support private object members, the way to make things private is to wrap them inside a block which effectively wraps them inside its own scope.
Now, if you were to use the above methods to create a new class and then try to extend it, for example by doing…
MyOtherClass.newMethod = function() { alert(privateVar); //no worky } |
I personally think that the fact that you can “append” new functionality to an object like this is very nice, but it has its problems.
The this keyword
This really confused me back in the day. Why would it sometimes not point at the object itself?
The usual case is events: If you assign a class member function as an event handler, the this keyword will not point to the object itself, but to something else, depending on the browser!
But how to access the object then?
var MyClass = function() { var self = this; return { eventHandler: function(event) { self.beep(); }, otherFunction: function() { alert('beep'); } }; }; |
Assign “this” to a variable in the scope of the function. Why didn’t I think of that?
No “extend”
How do you extend an object in JavaScript? Answer: You don’t… or not with a keyword, at least!
You can extend an object in JavaScript in the way you’d expect it to work in a class-based language, but it isn’t immediately obvious. You basically have to copy the prototype of the base-object to the child-object and add your new functionality to the child-object.
Luckily this is very simple these days, as most JS libraries provide an extension mechanism.
Due to the reasons mentioned in “member scope”, you will not be able to access private members in your child classes.
In closing
These are the four big things which confuse people in JavaScript OOP. At least they confused me a lot, and I admit they still do a bit. A lot of my JavaScript code is completely or almost completely procedural, but I’m working on learning the proper ways of OOP JS :D
What confuses you in JS?