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

来源:互联网 发布:淘宝天猫积分怎么兑换 编辑:程序博客网 时间:2024/05/24 15:42

原文地址:http://www.hoverlees.com/blog/?p=1193


javascript的prototype在新对象创建时会复制这个类的prototype到新的实例,但要注意,它不会完全复制值是对象的属性,而是复制对象的指针。另一方面,这样可以达到面象对象中的静态变量效果。

如下面的示例代码所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
functionA(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;
    }
};
vara=newA(10);
varb=newA(20);
varc=newA(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的静态变量定义方式呢)
正确的方式应该是在构造函数里声明对象,如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
functionA(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;
    }
};
vara=newA(10);
varb=newA(20);
varc=newA(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);
0 0