Where should I declare an instance variable in JavaScript?

12

I'm in doubt about creating instance variables in a class / JavaScript constructor function. I have read in several places that the declaration of an instance variable is made inside the body of the class as in the example below:

function Spam() {
    this.foo = "foo"
}

But I realized that I can also declare the variable in prototype of the class as in the example below:

Spam.prototype.bar = "bar";

And in the end I get the same result:

var mySpam = new Spam();
mySpam.foo    // => "foo": declarado no corpo da classe
mySpam.bar    // => "bar": declarado no prototype da classe

What is the difference between the two methods of declaring an instance variable?

    
asked by anonymous 11.01.2014 / 15:33

2 answers

10

foo is a variable only of the object you instantiated, while bar is of the prototype of the Spam (all objects) objects.

The difference is that in the first case each object has its own variable, while in the second all objects of that prototype share the same variable.

var mySpam2 = new Spam();

console.log(mySpam.bar); // "bar"
console.log(mySpam2.bar); // "bar"

Spam.prototype.bar = "qux";

console.log(mySpam.bar); // "qux"
console.log(mySpam2.bar); // "qux"

Notice that by changing the value of bar of the prototype this affected the access of that property on all Spam objects. With the property foo the same is not possible, since it is property of the object and not of the prototype.

Be careful not to hide the unintentionally

The correct way to change the value of the prototype is as I did in the example:

Spam.prototype.bar = "qux";

Notice that we are explicitly altering the prototype. Beware that the following, contrary to what may seem, not is equivalent:

mySpam2.bar = "baz";

In this case we did not change the prototype , we created a new property only on the object mySpam2 whose name is the same as that used in the prototype (" hiding" prototype on that object).

    
11.01.2014 / 16:09
4

The difference is that the variable declared in prototype is shared between all instances of the class. If it has a simple value, this does not matter, but if it is a complex variable (a list, or an object) then modifying its components will have side effects on the other objects of the class:

function Spam() {
    this.a = 10;
    this.b = [1,2,3];
}
Spam.prototype.c = 10;
Spam.prototype.d = [1,2,3];
Spam.prototype.print = function() {
    console.log(JSON.stringify({a:this.a, b:this.b, c:this.c, d:this.d}));
}

var s1 = new Spam();
var s2 = new Spam();

s1.print();
s2.print();

s1.a = 20;
s1.b[1] = 4;
s1.c = 20;
s1.d[1] = 4;

s1.print();
s2.print();

Result:

{"a":10,"b":[1,2,3],"c":10,"d":[1,2,3]}
{"a":10,"b":[1,2,3],"c":10,"d":[1,2,3]}

{"a":20,"b":[1,4,3],"c":20,"d":[1,4,3]}
{"a":10,"b":[1,2,3],"c":10,"d":[1,4,3]} 

Note that when you made s1.c = 20 it did not assigned Spam.prototype.c , but s1.c , so there was no side effect. But when you read s1.d and then modified one of its components (the second index), then you eventually changed the shared object.

So, by answering your question, the correct location of assigning any changeable instance variable is within the body of the class (constructor).

    
11.01.2014 / 16:10