javascript 闭包和原型

Posted

技术标签:

【中文标题】javascript 闭包和原型【英文标题】:javascript closures and prototypes 【发布时间】: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 已成为一个静态变量。 更改调用顺序不会改变结果。

【问题讨论】:

【参考方案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

【讨论】:

以上是关于javascript 闭包和原型的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript中高级进阶推荐一个JavaScript进阶深入系列专题系列(涉及原型作用域执行上下文变量对象this闭包按值传递callapplybindnew继承等

明白JavaScript原型链和JavaScrip继承

深入理解javascript原型和闭包(完结)

JavaScrip继承图文总结

深入理解javascript原型和闭包(完结)

javascript 闭包和原型