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继承等