Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

javascript closures and prototypes

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.

like image 821
user1728219 Avatar asked Jan 15 '23 09:01

user1728219


2 Answers

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>;
}
like image 199
jabclab Avatar answered Jan 19 '23 19:01

jabclab


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
like image 31
Mehran Avatar answered Jan 19 '23 21:01

Mehran