JavaScript面向对象(2)--属性分析及验证

1、私有属性分析

 1 function MyClass()
 2 {
 3     // 私有属性
 4     var privateName = "private";
 5 
 6     this.setPrivateName = function(value)
 7     {
 8         privateName = value;
 9     }
10         
11     this.getPrivateName = function()
12     {
13         return privateName;
14     }
15 }
16 
17 var object1 = new MyClass();
18 var object2 = new MyClass();
19 object1.setPrivateName("object1");
20 object1.setPrivateName("object2");
21 //弹出object1
22 alert(object1.getPrivateName());
23 //弹出object2
24 alert(object2.getPrivateName());

 

以上代码证明私有属性不能被不同对象共享,可以正常使用

2、window属性、方法分析

 1 function MyClass()
 2 {
 3     // window属性
 4     windowName = "window";
 5 
 6     this.setWindowName = function(value)
 7     {
 8         windowName = value;
 9     }
10         
11     this.getWindowName = function()
12     {
13         return windowName;
14     }
15 }
16 
17 var object1 = new MyClass();
18 var object2 = new MyClass();
19 object1.setWindowName("object1");
20 object1.setWindowName("object2");
21 //弹出object2
22 alert(object1.getWindowName());
23 //弹出object2
24 alert(object2.getWindowName());

 

以上代码证明Window属性被不同对象共享

下面还有更意外的情况

 1 function MyClass1()
 2 {
 3     // Window属性
 4     windowName = "window";    
 5     
 6     this.setWindowName = function(value)
 7     {
 8         windowName = value;
 9     }
10         
11     this.getWindowName = function()
12     {
13         return windowName;
14     }
15     
16     windowMethod = function()
17     {
18         alert("MyClass1");
19     }
20     
21     this.visitWindowMethod = function()
22     {
23         windowMethod();
24     }
25 }
26 
27 function MyClass2()
28 {
29     // Window属性
30     windowName = "window";
31     
32     this.setWindowName = function(value)
33     {
34         windowName = value;
35     }
36         
37     this.getWindowName = function()
38     {
39         return windowName;
40     }
41     
42     windowMethod = function()
43     {
44         alert("MyClass2");
45     }
46     
47     this.visitWindowMethod = function()
48     {
49         windowMethod();
50     }
51 }
52 
53 var object1 = new MyClass1();
54 var object2 = new MyClass2();
55 object1.setWindowName("object1");
56 object1.setWindowName("object2");
57 //弹出object2
58 alert(object1.getWindowName());
59 //弹出object2
60 alert(object2.getWindowName());
61 //弹出MyClass2
62 object1.visitWindowMethod();
63 //弹出MyClass2
64 object2.visitWindowMethod();

 

好吧,windowName和windowMethod虽然在类内定义,但实际上等于给window定义了windowName和windowMethod,所有的访问也都是针对window对象的属性和方法,所以当另一个对象或者类定义了相同的windowName和windowMethod时,之前的定义就被覆盖了。

windowName和window的属性没有任何区别,windowMethod却和window的方法有些区别。windowMethod可以访问类内的私有属性和私有方法,这是window的方法做不到的。这可是个不错的特性,不过这个特性可不好用。

让我们再做个实验吧

 1 function MyClass1()
 2 {
 3     // private属性
 4     var privateName = "MyClass1Private";    
 5     
 6     windowMethod = function()
 7     {
 8         alert(privateName);
 9     }
10     
11     this.visitWindowMethod = function()
12     {
13         windowMethod();
14     }
15 }
16 
17 function MyClass2()
18 {
19     // private属性
20     var privateName = "MyClass2Private";    
21     
22     windowMethod = function()
23     {
24         alert(privateName);
25     }
26     
27     this.visitWindowMethod = function()
28     {
29         windowMethod();
30     }
31 }
32 
33 var object1 = new MyClass1();
34 var object2 = new MyClass2();
35 //弹出MyClass2Private
36 object1.visitWindowMethod();
37 //弹出MyClass2Private
38 object2.visitWindowMethod();

 惊讶吗,访问的竟然都是MyClass2的属性。

windowName和windowMethod要慎用,这种不加var的定义方法会是个很大的坑,所以建议大家不要使用。

3、this定义的公有属性分析

 1 function MyClass()
 2 {
 3     // public
 4     this.publicName = "public";    
 5 }
 6 
 7 var object1 = new MyClass();
 8 var object2 = new MyClass();
 9 object1.publicName = "object1";
10 object2.publicName = "object2";
11 //object1
12 alert(object1.publicName);
13 //object2
14 alert(object2.publicName);

 这个就没什么好说的了,和其他语言一样。

4、prototype定义的公有属性分析

 1 function MyClass()
 2 {
 3     
 4 }
 5 MyClass.prototype.publicName = "public";
 6 var object1 = new MyClass();
 7 var object2 = new MyClass();
 8 
 9 //public
10 alert(object1.publicName);
11 //public
12 alert(object2.publicName);
13 object1.publicName = "object1";
14 object2.publicName = "object2";
15 //object1
16 alert(object1.publicName);
17 //object2
18 alert(object2.publicName);
19 //public
20 alert(MyClass.prototype.publicName);
21 
22 object1.constructor.prototype.publicName = "object1prototype";
23 object2.constructor.prototype.publicName = "object2prototype";
24 //object1
25 alert(object1.publicName);
26 //object2prototype
27 alert(object1.constructor.prototype.publicName);
28 //object2
29 alert(object2.publicName);
30 //object2prototype
31 alert(object2.constructor.prototype.publicName);
32 //object2prototype
33 alert(MyClass.prototype.publicName);

 

这个例子相信也产生了一些意外,这和JavaScript的对象生成方式有关,我们可以把JavaScript的类看作是一个模板,每次生成对象时都将在类内定义的属性、方法和类外通过prototype定义的属性、方法(私有属性、私有方法、公有属性、公有方法)拷贝到对象中不拷贝类外定义的静态属性和静态方法。

拷贝完成后对象和模板唯一的关联就是constructor,对象可以通过constructor访问模板。

这下上面的例子应该好理解了,constructor.prototype.publicName是更改了模板中的属性,object1.publicName只是改变了object1对象这个拷贝中的属性。

 

5、静态属性分析 

上面其实也解释了静态属性的原理,静态属性其实是MyClass这个模板的属性,只存在与模板之中,对象并不含有这个属性。对象想访问静态属性只能通过constructor。

 1 function MyClass()
 2 {
 3     
 4 }
 5 MyClass.staticName = "static";
 6 var object1 = new MyClass();
 7 var object2 = new MyClass();
 8 object1.staticName = "object1";
 9 object2.staticName = "object2";
10 //object1
11 alert(object1.staticName);
12 //object2
13 alert(object2.staticName);
14 //static
15 alert(MyClass.staticName)
16 
17 object1.constructor.staticName = "object1";
18 object2.constructor.staticName = "object2";
19 //object2
20 alert(object1.constructor.staticName);
21 //object2
22 alert(object2.constructor.staticName);
23 //object2
24 alert(MyClass.staticName);

 

这个例子很好的说明了静态属性的使用方式,对象要通过constructor访问,类可以直接访问。上面的object1.staticName = "object1"其实给object1添加了一个名为staticName的公共属性,并没有为静态属性赋值。

 

6、补充:公有方法分析

突然又想起一个问题,如果同时通过this和prototype的方式定义了同名的公有方法和公有属性,调用时会访问哪个方法和哪个属性呢

 1 MyClass = function()
 2 {
 3     this.name = "thisName"
 4     
 5     this.getName = function(){
 6         return  "thisFunction." + this.name;
 7     };
 8 }
 9 
10 MyClass.prototype.name = "protoName"
11 MyClass.prototype.getName = function(){
12         return  "protoFunction." + this.name;
13     };
14 
15 a = new MyClass();
16 // 调用this.getName和this.name
17 alert(a.getName());

 

posted @ 2014-09-05 14:12  supermancoke  阅读(572)  评论(0编辑  收藏  举报