js面向对象-动态原型方法

最近在读javascript高级程序设计,其中的对象基础一章感觉讲的很好,下面把其中有用的东西分享一下。

看如下js构造类的一个示例:

Js代码   收藏代码
  1. function Car(sColor, iDoors, iMpg) {  
  2.                                this.color = sColor;  
  3.                 this.doors = iDoors;  
  4.                 this.mpg = iMpg;  
  5.                 this.showColor = function() {  
  6.                     alert(this.color);  
  7.                 }  
  8.             }  
  9. var oCar1 = new Car('red', 4, 23);  
  10. var oCar2 = new Car('blue', 3, 25);  

 这种方法被称为构造函数方式 。简要的说明一下,这段代码声明了一个Car类,oCar1和oCar2为其两个对象。看起来这段代码很是不错,但是注意那个this.showColor = function(){alert(this.color)};

this指代Car的一个对象,也就是说,每一个对象都有一个showColor方法,这势必会造成一种资源浪费。

再来看一种js构造类的示例:

Js代码   收藏代码
  1. function Car(){  
  2. }  
  3. Car.prototype.color = "red";  
  4. Car.prototype.doors = 4;  
  5. Car.prototype.mpg = 23;  
  6. Car.prototype.showColor = function(){  
  7.       alert(this.color);  
  8. }  
  9. var oCar1 = new Car();  
  10. var oCar2 = new Car();  

这种方法被称为原型方式 。该方法避免了showColor函数被每个对象都创建,而是所有Car类的对象共享这一个函数,然后在调用的时候,使用this关键字找到实例对象的color,这种方式也有问题,即color,doors和mpg被所有对象共享,如果一个对象修改了color那么其他的对象的color也会相应的改变。

那么显然将二者结合起来就好了:

Js代码   收藏代码
  1. function Car(){  
  2.   
  3.   
  4.       this.color = sColor;  
  5.   
  6.   
  7.       this.doors = iDoors;  
  8.   
  9.   
  10.       this.mpg = iMpg;  
  11.   
  12.   
  13. }  
  14.   
  15.   
  16. Car.prototype.showColor = function(){  
  17.   
  18.   
  19.       alert(this.color);  
  20.   
  21.   
  22. }  
  23.   
  24.   
  25. var oCar1 = new Car();  
  26.   
  27.   
  28. var oCar2 = new Car();  

这种方式被称为混合的构造函数/原型方法 。

这个代码就没有什么问题了,那么动态原型方法 指的是什么呢?

我们先来看一段java代码:

Java代码   收藏代码
  1. class Car {  
  2.   
  3.   
  4.       public String color = "red";  
  5.   
  6.   
  7.       public int doors = 4;  
  8.   
  9.   
  10.       public int mpg = 23;  
  11.   
  12.   
  13.       public Car(String color, int doors, int mpg){  
  14.   
  15.   
  16.               this.color = color;  
  17.   
  18.   
  19.               this.doors = doors;  
  20.   
  21.   
  22.               this.mpg = mpg;  
  23.   
  24.   
  25.       }  
  26.   
  27.   
  28.       public void showColor() {  
  29.   
  30.   
  31.                System.out.println(this.color);  
  32.   
  33.   
  34.       }  
  35.   
  36.   
  37. }  

 这是和我们前面js构造出来的相似的一个java class.由此可见由于java超强的面向对象的机制,已经把这种属性和方法的区别为我们做好了,我们只需要将所有的方法写在class中,然后java处理好剩下的事情。

js也有一种几乎完全和这段java类似的方法-动态原型方法

Js代码   收藏代码
  1. function Car(sColor,iDoors,iMpg){  
  2.   
  3.   
  4.       this.color = sColor;  
  5.   
  6.   
  7.       this.doors = iDoors;  
  8.   
  9.   
  10.       this.mpg = iMpg;  
  11.   
  12.   
  13.       if(typeof Car._initialized == "undefined"){  
  14.   
  15.   
  16.               Car.prototype.showColor = function(){  
  17.   
  18.   
  19.                          alert(this.color);  
  20.   
  21.   
  22.               }  
  23.   
  24.   
  25.               Car._initialized = true.  
  26.   
  27.   
  28.       }  
  29.   
  30.   
  31. }  

 这回看起来舒服多了吧,不过动态原型方法 在继承的时候有一个问题:

Js代码   收藏代码
  1. function Polygon(iSides) {  
  2.   
  3.   
  4.         this.sides = iSides;  
  5.   
  6.   
  7.         if(typeof Polygon._initialized == "undefined"){  
  8.   
  9.   
  10.             Polygon.prototype.getArea = function(){  
  11.   
  12.   
  13.                 return 0;  
  14.   
  15.   
  16.             }  
  17.   
  18.   
  19.             Polygon._initialized = true;  
  20.   
  21.   
  22.         }  
  23.   
  24.   
  25.     }  
  26.   
  27.   
  28.     function Triangle(iBase,iHeight){  
  29.   
  30.   
  31.         Polygon.call(this,3);  
  32.   
  33.   
  34.         this.base = iBase;  
  35.   
  36.   
  37.         this.height = iHeight;  
  38.   
  39.   
  40.         if(typeof Triangle._initialized == "undefined"){  
  41.   
  42.   
  43.             Triangle.prototype = new Polygon();  
  44.   
  45.   
  46.             Triangle.prototype.getArea = function(){  
  47.   
  48.   
  49.                 return .5 * this.base * this.height;  
  50.   
  51.   
  52.             }  
  53.   
  54.   
  55.             Triangle._initialized = true;  
  56.   
  57.   
  58.         }  
  59.   
  60.   
  61.     }  
  62.   
  63.   
  64. var tri1 = new Triangle(3,4);  
  65.   
  66.   
  67. alert(tri1.getArea());  

 这段代码根本就跑不起来,也就是说当

Js代码   收藏代码
  1. var tri1 = new Triangle(3,4);  

执行的时候,程序会进入Triangle的构造函数中,然后依次执行,此时Triangle的这个对象已经被实例化了,所以当再次调用

Js代码   收藏代码
  1. Triangle.prototype = new Polygon();  

自然就会报错了。也就是说,动态原型方法 不适合与继承中子类的构造。

那么修改一下就可以了:

Js代码   收藏代码
  1. function Polygon(iSides) {  
  2.   
  3.   
  4.         this.sides = iSides;  
  5.   
  6.   
  7.         this.type = "Polygon";  
  8.   
  9.   
  10.         if(typeof Polygon._initialized == "undefined"){  
  11.   
  12.   
  13.             Polygon.prototype.getArea = function(){  
  14.   
  15.   
  16.                 return 0;  
  17.   
  18.   
  19.             }  
  20.   
  21.   
  22.             Polygon._initialized = true;  
  23.   
  24.   
  25.         }  
  26.   
  27.   
  28.     }  
  29.   
  30.   
  31.     function Triangle(iBase,iHeight){  
  32.   
  33.   
  34.         Polygon.call(this,3);  
  35.   
  36.   
  37.         this.base = iBase;  
  38.   
  39.   
  40.         this.height = iHeight;  
  41.   
  42.   
  43.         if(typeof Triangle._initialized == "undefined"){  
  44.   
  45.   
  46.             Triangle.prototype.getArea = function(){  
  47.   
  48.   
  49.                 return .5 * this.base * this.height;  
  50.   
  51.   
  52.             }  
  53.   
  54.   
  55.             Triangle._initialized = true;  
  56.   
  57.   
  58.         }  
  59.   
  60.   
  61.     }  
  62.   
  63.   
  64.     Triangle.prototype = new Polygon();  
  65.   
  66.   
  67.     var tri1 = new Triangle(3,4);  
  68.   
  69.   
  70.     alert(tri1.getArea());  
  71.   
  72.   
  73.        alert(tri1.type);  

你可能感兴趣的:(js)