Wednesday, June 15, 2011

javascript prefer literal notation than constructor function

In javascript, we can create an object using object literal:
var obj = {};

We can also create an object using constructor function:
var obj = new Object();

I think most people from other OOP background will feel more comfortable with using constructor function. That was exactly what i did until i learned that it is not encouraged in javascript.

So, why do we say we should favor literal notation over constructor function?
1. literal notation is obviously shorter to type. Although for me, that is not a big deal. If constructor function can make things easier to understand and help reduce confusion, i don't mind typing a bit more.
2. It emphasizes that javascript objects are simply mutable hashes and not something that needs to be baked from a “recipe” (from a class). Well, this reason sounds more decent to me.
3. the Object() constructor accepts a parameter and, depending on the value passed, it may decide to delegate the object creation to another built-in constructor and return a different object than you expect.

// an empty object
var o = new Object();
console.log(o.constructor === Object); // true

// a string object
var o = new Object("I am a string");
console.log(o.constructor === String); // true

// normal objects don't have a substring() method,
// but string objects do
console.log(typeof o.substring); // "function"

This behavior of the Object() constructor can lead to unexpected results when the value you pass to it is dynamic and not known until runtime.

Let's have a look at Array literal. To declare an array, we can simply do:
var a = []
var a = new Array();

There is one obvious reason we should definitely avoid using Array constructor. Let's check through it in details. Say we create arrays with elements 1,2,3
//using literal

var a = [1,2,3];
//using constructor
var b = new Array(1,2,3);
//so far so good
for(var i=0; i<3; i++){

Everything looks fine. Now, we simply want to create an array with element 1;
//using literal
var a = [1];

//using constructor
var b = new Array(1);
//now see the funny part
console.log(a[0]) //no problem, we get 1
console.log(b[0])//big problem! we get 'undefined'!!!

How come this happen? It turns out that when we pass a single number to the Array() constructor, it doesn’t become the value of the first array element. It sets the length of the array instead! So, new Array(1) creates an array with length of 1, but no actual elements! How awful it is!

What if we do var b = new Array(3.14)? Well, you will simply get "RangeError: invalid array length"

No comments: