2012-10-08 46 views
4

我想我已經明白關閉的愛迪,但下面的代碼 表現令人驚訝的對我說:JavaScript的關閉和原型

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 

如果原型方法從 實例方法的行爲不同,我可以理解,但是這看起來像x已經成爲一個靜態變量。 更改通話順序不會改變結果。

回答

2

這裏的靜態成員是A.prototype.getX2。第二次致電A.prototype.getX2 = function() { return x; }(由於var a2 = new A(2);)將取代第一個。要了解它,你可以扭轉實例的順序:

var a2 = new A(2); 
var a1 = new A(1); 

那麼你就必須:

a1.getX1()=1 
a2.getX1()=2 
a1.getX2()=1 
a2.getX2()=1 
4

當您更改prototype你改變給定的function所有實例類,包括那些已經存在的

因此,當你呼喚我

A.prototype.getX2 = function() { return x; } 

你的設置,對的A現有a1實例。因此,有效地你結束了下面的僞代碼:

<all instances of A>.getX2 = function() { 
    return <latest value of x passed to A constructor>; 
} 
1

你已經寫

function A(x) 
{ 
    this.getX1 = function() { return x; } 
    A.prototype.getX2 = function() { return x; } 
} 

此構造覆蓋每次A.prototype.getX2

所以第一

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. 

因此,它應該是這樣的

function A(x) 
{ 
    this.getX1 = function() { return x; } 
} 

A.prototype.getX2 = function() { return this.getX1(); } 
2

你定義的getX2兩次,每次您創建一個新A.該功能的結果永遠是最後X.考慮改寫這樣的代碼:

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​​​ 

這樣,你只定義一次的getX2和它的作品作爲預期。

+0

謝謝。這讓我很清楚。 – user1728219

+0

不客氣:) – Peeter