I thought I have understood the idee of closures, but the following code behaves surprisingly for me:
function A(x)
{
this.getX1 = function () { return x; }
A.prototype.getX2 = function () { return x; }
}
var a1 = new A(1);
var a2 = new A(2);
console.log ('a1.getX1()=%d', a1.getX1 ()); // 1
console.log ('a2.getX1()=%d', a2.getX1 ()); // 2
console.log ('a1.getX2()=%d', a1.getX2 ()); // 2 ???
console.log ('a2.getX2()=%d', a2.getX2 ()); // 2
I could understand if prototype methods behave differently from instance methods, but this looks like x has become a static variable. Changing the order of calls does not change results.
When you change the prototype
you're changing the function
for all instances of the given class, including those that already exist.
Therefore when you call...
A.prototype.getX2 = function () { return x; }
You're setting that for the existing a1
instance of A
. So effectively you're ending up with the following pseudo code:
<all instances of A>.getX2 = function () {
return <latest value of x passed to A constructor>;
}
The static member here is A.prototype.getX2
. The second call to A.prototype.getX2 = function () { return x; }
(due to var a2 = new A(2);
) replaces the first one. To understand it you can reverse the order of instantiations:
var a2 = new A(2);
var a1 = new A(1);
Then you'll have:
a1.getX1()=1
a2.getX1()=2
a1.getX2()=1
a2.getX2()=1
You're defining getX2 twice, each time you create a new A. The result for that function will always be the last X. Considering rewriting your code like this:
function A(x) {
this.x = x;
this.getX1 = function() {
return this.x;
}
}
A.prototype.getX2 = function() {
return this.x;
}
var a1 = new A(1);
var a2 = new A(2);
console.log('a1.getX1()=%d', a1.getX1()); // 1
console.log('a2.getX1()=%d', a2.getX1()); // 2
console.log('a1.getX2()=%d', a1.getX2()); // 1
console.log('a2.getX2()=%d', a2.getX2()); // 2
This way, you only define getX2 once and it works as expected.
You have written
function A(x)
{
this.getX1 = function () { return x; }
A.prototype.getX2 = function () { return x; }
}
This constructor overwrites A.prototype.getX2
each time.
So first
var a1 = new A(1); // This invokes A and adds a function `getX2` to the prototype of `A`which returns `x` that is `1`
var a2 = new A(2); // This invokes A and overwrites the function `getX2` in the prototype of `A` with a function which returns `x` that is `2` now.
So it should be like this
function A(x)
{
this.getX1 = function () { return x; }
}
A.prototype.getX2 = function () { return this.getX1(); }