我在尝试让类变量在javascript中工作时遇到了一些麻烦.
我以为我理解了原型继承模型,但显然不是.我假设由于原型将在对象之间共享,因此它们的变量也是如此.
这就是为什么这段代码让我困惑的原因.
实现类变量的正确方法是什么?
function classA() {}; classA.prototype.shared = 0; a = new classA; //print both values to make sure that they are the same classA.prototype.shared; a.shared; //increment class variable classA.prototype.shared++; //Verify that they are each 1 (Works) classA.prototype.shared; a.shared; //now increment the other reference a.shared++; //Verify that they are each 2 (Doesn't Work) classA.prototype.shared; a.shared;
更新:所以似乎每个人都在确认通过递增实例的变量这一事实我们不会影响原型.这很好,这是我在我的例子中记录的内容,但这不是在语言设计中出现错误吗?为什么这种行为是可取的?我觉得奇怪的是,当实例的var未定义时,我们遵循原型的隐藏链接,我们得到var的值,但我们将它复制到实例对象中.
我也明白这不是java/c ++/ruby/python,它是一种不同的语言.我只是好奇为什么这种行为可能会很好.
静态(类级别)变量可以像这样完成:
function classA(){ //initialize } classA.prototype.method1 = function(){ //accessible from anywhere classA.static_var = 1; //accessible only from THIS object this.instance_var = 2; } classA.static_var = 1; //This is the same variable that is accessed in method1()
由于javascript处理原型的方式,你的输出看起来很奇怪.调用任何方法/ retreiving实例化对象的变量首先检查实例,然后检查原型.即
var a = new classA(); classA.prototype.stat = 1; // checks a.stat which is undefined, then checks classA.prototype.stat which has a value alert(a.stat); // (a.stat = undefined, a.prototype.stat = 1) // after this a.stat will not check the prototype because it is defined in the object. a.stat = 5; // (a.stat = 5, a.prototype.stat = 1) // this is essentially a.stat = a.stat + 1; a.stat++; // (a.stat = 6, a.prototype.stat = 1)
I assumed that since prototypes will be shared between objects then so will their variables.
它们是,但是这个:
a.shared++
没有做你认为它正在做的事情.它实际上(大约)糖语法:
(a.shared= a.shared+1)-1
(-1表示返回预增量值,而不是您实际使用的是retrun值,但仍然.)
所以这实际上是对a.shared做了一个分配.当您分配给实例成员时,您始终会写入该实例自己的成员,而不是触及任何原型的任何成员.这跟说:
classA.prototype.shared= 1; a.shared= 2;
所以你的新a.shared会隐藏prototype.shared而不会改变它.classA的其他实例将继续显示原型的值1.如果删除a.shared,您将再次能够看到隐藏在其后面的原型变量.
如果你想拥有一个类变量,比如Java中的静态变量,那么你可以在父类中声明一个变量,但是你不应该将它作为子对象的变量来访问.本文有一个很好的示例,即Circle类具有变量,Circle.PI = 3.14
而Circle的所有实例都将其作为Circle.PI
(而不是c.PI
)访问.
所以我的答案是,如果你想要一个类变量shared
,classA
那么你应该声明共享的变量classA
,之后你应该使用classA.shared
而不是a.shared
.改变a.shared
永远不会导致classA.shared
改变.