【问题标题】:javascript closures and prototypesjavascript 闭包和原型
【发布时间】:2012-09-28 11:57:07
【问题描述】:

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

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

【问题讨论】:

    标签: javascript node.js closures prototype


    【解决方案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 即可按预期工作。

      【讨论】:

        【解决方案3】:

        当您更改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>;
        }
        

        【讨论】:

          【解决方案4】:

          这里的静态成员是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
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-05-08
            • 1970-01-01
            • 2011-04-03
            • 1970-01-01
            • 2023-03-16
            • 1970-01-01
            相关资源
            最近更新 更多