JavaScript闭包和原型

4

我本以为理解了闭包的概念,但下面的代码对我来说表现得出乎意料:

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变成了一个静态变量。更改调用顺序不会改变结果。

4个回答

4
当你改变一个类的原型(prototype)时,你正在改变所有该类实例的function,包括那些已经存在的实例。
因此,当你调用...
A.prototype.getX2 = function () { return x; }

您正在为现有的 a1 实例化对象 A 设置该属性。因此,您最终将得到以下伪代码:

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

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

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,它就会按预期工作。


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(); }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接