JavaScript prototype gotchas

Published November 13, 2012

JavaScript is a strange language:

12345678910
MyClass = function() {};

MyClass.prototype.myProperty = [];

var a = new MyClass();
var b = new MyClass();

a.myProperty[0] = 'xyz';

console.log(b.myProperty[0]); // prints 'xyz'

The issue here is one of prototypes and references. In most OO languages, defining a property on a class is done so in such a way that each instance of that class has a property completely independent of all other instances. Even if it's a reference, it still gets a reference to its *own* value.

In JavaScript, things are a bit wacky. Mostly they work as normal (with strange syntax), but occasionally things like this trip you up. It happens because, as you can see, both a and b have a reference to the same object; the one assigned to the prototype. This is only a problem with 'rich' types like arrays and objects, immutable types like string and primitives sort themselves out.

The way to avoid it is to assign 'myProperty' within the constructor:

123
MyClass = function() {
    this.myProperty = [];
};

It's strange that JSLint doesn't pick up on this.

For what it's worth, gjslint (Google's closure linter) will emit:

Line 3, E:0100: Member MyClass.prototype.myProperty cannot have a non-primitive value

but I find Google's linter is generally not as universally useful as JSLint (it's better for Closure development though, i.e. if you're planning to feed your source through the Closure Compiler).