Wednesday, June 18, 2008

OOP in Javascript... Don't be fooled.

In JavaScript, "new" does not mean you get a clean instance of a class. class properties still have a link reference to the prototype. Here is an example of the problem.

//example class
var testClass = function(){};
//class definition
testClass.prototype = { arr: [], obj: {} };

/*
* This example shows how instance 2
* indirectly gets instance1's array
*/

//new instance 1
var instance1 = new testClass();
//push some stuff in the array
instance1.arr.push('this is data 1 for instance 1');
instance1.arr.push('this is data 2 for instance 1');
instance1.arr.push('this is data 3 for instance 1');

//new instance 2
var instance2 = new testClass();

//instance2 has instance1's array!
alert(instance2.arr);


/*
* This example shows how instance 1
* indirectly gets instance2's object
*/
//put some stuff in instance2's obj
instance2.obj['one'] = 'this is data 1 for instance 2';
instance2.obj['two'] = 'this is data 2 for instance 2';
instance2.obj['three'] = 'this is data 3 for instance 2';

//instance1's obj was changed to instance2's obj!
alert(instance1.obj.one + ' ' + instance1.obj.two + ' ' + instance1.obj.three);

The solution that works is using Object.clone(new testClass) after instantiation, however not very optimal. So in the end I made sure in my constructor class, I manually reset arr and obj (this.arr = []; this.obj = {}). It's important that if you use "new testClass" you are not making a real instantiation, it's more like a simulated one. Plan on manually resetting array and object properties in your constructor so this won't happen to you!