Some time ago I left my safe ruby & Objective-C lands to get into the bushy and wild javascript jungle. But surprise! it wasn’t that wild and there were some very mature and fun actors in here! Namely node.js and the V8 engine.
So, here are a few of the things I think I learned about javascript:
1 – Javascript is prototype based
Although some people may claim that javascript is an OOP language, I like to think that javascript is actually prototype based with lots of functional programming influence. Don’t get me wrong though, you can actually do some serious OOP with javascript (more on that later)
2 – Javascript can be fun!
Take for instance, jquery & jquery ui. Both of them are very well designed frameworks and actually very good programming practices.
3 – Namespaces
Although there are no actual namespaces, you can simulate them encapsulating functions/variables/objects inside other objects, for instance:
1
2
3
4
5
6
7
8
9
10
11
12
|
function foo() {
console.log("global foo");
}
// empty object
var ns = {};
ns.foo = function () {
console.log("foo inside ns");
}
foo();
ns.foo();
|
This takes into consideration that the definition is made under the “global” namespace, which would be window’s closure. One way to make sure this is the wanted behaviour is to be explicit:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
(function (window) {
function foo() {
...
}
var ns = {};
ns.foo = function () {
...
}
// explicitly export symbols to the global namespace
window['foo'] = foo;
window['ns'] = ns;
})(window);
|
By creating the anonymous function (which receives as a single parameter the window object — you can pass other objects here if you want), you use your private closure inside: this way you do not contaminate the global namespace and only export the symbols you really want to export.
4 – Classes, Objects and being nice
In many places, you will see that the usual way to create a class is something like this:
1
2
3
4
5
6
7
8
9
10
|
// option 1
function MyClass() {
}
// option 2
var MyClass = function () {
}
// both options let you do this:
var obj = new MyClass();
|
What happens here is that the constructor is also the definition of the prototype for future objects, so things can get messy… In the end, looking at how frameworks like jquery & others do things, I opted for this way:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
// empty definition
var MyClass = function () {};
var MyClass__prototype = {
attribute1: "something",
attribute2: null,
// these are instance functions/methods
foo: function () {
},
bar: function () {
}
}
// these are class functions
MyClass.class_function1 = function () {
}
MyClass.class_function2 = function () {
}
MyClass.prototype = MyClass__prototype;
MyClass.create = function () {
var o = new MyClass();
// initialize o here
...
return o;
}
// usage:
var someObject = MyClass.create();
|
This way, the constructor is clearly separated from the class definition, leaving no garbage in the object’s namespace.
5 – Add “static” typing through comments and check with closure compiler
Google’s closure compiler is a very handy tool that lets you “compile” your javascript code, but it also checks the code for common mistakes and also, if you comment your code The Right Way® then it also type-checks your code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
/**
* @constructor {SomeClass}
*/
var SomeClass = function() {};
var SomeClass__prototype = {
/**
* the position of the object
* @type {Object.<string,number>
*/
position: { 'x': 0, 'y': 0},
/**
* this object's children
* @type {Array.<SomeClass>}
*/
children: [],
/**
* adds a child - z and tag are optional
*
* @param {SomeClass} child
* @param {number=} z
* @param {string=} tag
* @return {SomeClass}
*/
addChild: function (child, z, tag) {
}
};
|
Anyway… you get the idea. The whole thing is very inspired in jdoc and you should check the reference.
In order to compile the code, you can download the application (a .jar) and run it from the command line, or use the online application.
This is highly recommended for every javascript project since it will let you catch silly errors.
6 – Object properties are COW (at least on V8)
NOTE1 this is just an assumption of mine. Didn’t have the time to check it.
NOTE2 this is just something funny and not really relevant, but I find it very interesting.
When debugging my application I created a few simple objects just to see how they look under the debugger and also to learn a little bit more. So take for instance this simple example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
var A = function () {};
var A__prototype = {
prop1: "lala",
prop2: "lolo"
}
A.prototype = A__prototype;
A.create = function () {
// simplest constructor ever
return new A();
}
// now test the code
var a = A.create();
console.log(a.prop1);
console.log(a.prop2);
a.prop1 = "something else";
console.log(a.prop1);
console.log(a.prop2);
|
If you place that simple example on an html page and load it in Chrome and check the debug console, you will see what you expect:

But if you set a breakpoint on the creation line, and trace through the code, something interesting appears:

As you can see, the object a is empty, but the prototype shows the properties as expected:

but… as soon as the property is written, it is “promoted” to the object’s closure:

Which I think is really cool :-)
UPDATE: This whole point is basically the result of javascript being prototype-based: an object holds reference to a common prototype, until it needs to be different, in this case, when the property changes specifically in the context of that particular object.
So what happens when you modify nested objects? take for instance the updated example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
var A__prototype = {
prop1: "lala",
prop2: "lolo",
prop3: {
'x': 0,
'y': 100
}
}
var b1 = A.create();
var b2 = A.create();
console.log(b1.prop3);
console.log(b2.prop3);
b1.prop3.x = 500;
console.log(b1.prop3);
console.log(b2.prop3);
|
If you set a breakpoint right before the creation of b1, you will notice that when you modify b1.prop3.x, it is also modified in b2. This is obviously not the intended behaviour. One way to fix this is with accessors and setters:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
var A__prototype = {
prop1: "lala",
prop2: "lolo",
prop3: {
'x': 0,
'y': 100
},
setProp3: function (x, y) {
this.prop3 = {
'x': x,
'y': y
}
}
}
var b1 = A.create();
var b2 = A.create();
console.log(b1.prop3);
console.log(b2.prop3);
b1.setProp3(500, 100);
console.log(b1.prop3);
console.log(b2.prop3);
|
By doing it this way, prop3 is modified the way we wanted. This is actually very important and you might want to take that into account when creating complex objects and inserting them in the prototype.

Conclusions
I have to admit that coming from a language that is as beautiful and simple as ruby, I was a bit afraid of testing javascript, specially since most of what I remember of javascript is what I learned in the 90s. After giving another look at javascript and seeing that if you commit yourself to respect the good practices, javascript can be quite fun!
In the end, I hope that some of the lessons I learned from re-learning javascript might be useful to you.