javascript的prototype在新对象创建时会复制这个类的prototype到新的实例,但要注意,它不会完全复制值是对象的属性,而是复制对象的指针。另一方面,这样可以达到面象对象中的静态变量效果。
如下面的示例代码所示:
function A(num){ this.num=num; this.inner.instanceNum++; } A.prototype={ num:0, inner:{ instanceNum:0, invokeNum:0 }, setNum:function(num){ this.num=num; this.inner.invokeNum++; }, toString:function(){ return "Num:"+this.num+" instanceNum:"+this.inner.instanceNum+" setNum:"+this.inner.invokeNum; } }; var a=new A(10); var b=new A(20); var c=new A(30); a.setNum(100); b.setNum(200); b.setNum(200); c.setNum(300); c.setNum(300); c.setNum(300); alert(a); alert(b); alert(c);
这段代码咋一看,执行完成后所有对象inner.instanceNum都应该等于1,a的inner.invokeNum=1,b的是2,c的是3
而程序的真正输出是
Num:100 instanceNum:3 setNum:6
Num:200 instanceNum:3 setNum:6
Num:300 instanceNum:3 setNum:6
所以如果使用prototype方式的面向对象编程,在原型的定义里,属性的值不能是对象,否则它相当于标准面象对象里的静态变量了(但这正好是js的静态变量定义方式呢)
正确的方式应该是在构造函数里声明对象,如下
function A(num){ this.num=num; this.inner={ instanceNum:0, invokeNum:0 }; this.inner.instanceNum++; } A.prototype={ num:0, inner:null, setNum:function(num){ this.num=num; this.inner.invokeNum++; }, toString:function(){ return "Num:"+this.num+" instanceNum:"+this.inner.instanceNum+" setNum:"+this.inner.invokeNum; } }; var a=new A(10); var b=new A(20); var c=new A(30); a.setNum(100); b.setNum(200); b.setNum(200); c.setNum(300); c.setNum(300); c.setNum(300); alert(a); alert(b); alert(c);