javascript闭包和原型

时间:2012-10-08 08:50:01

标签: javascript node.js closures prototype

我以为我已经理解了闭包的概念,但是下面的代码 我的表现令人惊讶:

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 个答案:

答案 0 :(得分: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>;
}

答案 1 :(得分: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 :(得分:2)

每次创建新的A时,你都会定义两次getX2。该函数的结果将始终是最后的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,它就会按预期工作。

答案 3 :(得分: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(); }