javascript中prototype方式面向对象编程注意事项

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);

Leave a comment

Your email address will not be published. Required fields are marked *