A JavaScript Object Oriented Programming Technique
There are many conflicting approaches to object oriented programming in JavaScript. On the one hand, the language was designed with prototypal object oriented programming in mind, with the only built-in mechanism for inheritance being object inheritance. However, the language is also fitted with a new
keyword of dubious quality which shows aspects of a more traditional class based OO programming.
Douglas Crockford presented in his book JavaScript: The Good Parts one of the earliest techniques of consistent OO programming. However, I found it quite outdated, and after some of research and experimentation, I came up with the following technique which I now use in Exposition.
// Namespace
var ph = ph || {};
ph.barthe = ph.barthe || {};
// Use strict header
(function() {
"use strict";
// Class declaration
ph.barthe.MyClass = function(ctr_param) {
// Remap this
var self = this;
// Private variable
var m_private_var;
// Private method
var privateMethod = function(param) {
// ...
};
// Public method
self.publicMethod = function(param) {
// ...
};
// Constructor body
(function() {
// Temporary variable i, does not leak
for (var i=0; i<ctr_param; ++i)
m_private_var += privateMethod(i);
self.publicMethod('stuff');
})();
};
// Object usage
var ph.barthe.exampleUsage = function() {
var my_instance = new ph.barthe.MyClass(15);
return my_instance.publicMethod('other stuff');
};
// Use strict footer
})();
In the previous code sample, I employed the following techniques:
-
Use pseudo namespaces to avoid cluttering the global namespace and avoid potential naming conflicts with third party scripts. The namespace is in reality a single global object to which properties are appended. The OR operator in
var ph = ph || {};
is used to make sure the object is only created if it does not already exist. This makes the code tolerant to changes in the order<script>
statements. -
Use ECMAScript 5 strict mode. This is what the seemingly useless
"use strict"
statement is about. Instead of adding the statement to every function, I create an anonymous function whose scope is the entire file, and execute it immediately in the static context. -
Use “classical” OO programming with constructor functions instead of prototypes. I am more familiar with classical OO programming and the upcoming ECMAScript 6 is going to add support for classes. But a more pragmatic reason for that choice, is that relying on closures within constructor functions, appears to be the only known technique to get private members in JavaScript.
-
Use the
new
keyword instead ofObject.create
or some kind of custom make function. I think it signals my intent to use classical OO programming more clearly. The ECMAScript 5 strict mode fixes the main argument Crockford uses against the “new” keyword. In non-strict mode, if you forget to usenew
when you invoke a constructor function,this
ends up pointing to the global context instead of the object itself. This can lead to silent failures of disastrous consequences. In strict mode, an exception is raised instead, making the mistake obvious. In addition, naming conventions enforced by JSHint and JSLint help mitigate this risk. -
Use
self = this
to avoid the confusing remapping ofthis
. This article illustrates howthis
is dynamically remapped and why we need to keep a reference to the original value. This is a variant of thethat = this
technique also mentioned by Crockford. I preferself
because I am familiar with ObjectiveC andthis
andthat
look too similar to my eyes. -
Use an anonymous function for the constructor body. Otherwise, temporary variables can leak to clutter the constructor closure forever. I believe this pattern also increase the readability of the code, by restricting statements outside the constructor body to mere assignments. This reduces the amount of code to scan.