看如下js构造类的一个示例:
- function Car(sColor, iDoors, iMpg) {
- this.color = sColor;
- this.doors = iDoors;
- this.mpg = iMpg;
- this.showColor = function() {
- alert(this.color);
- }
- }
- var oCar1 = new Car('red', 4, 23);
- var oCar2 = new Car('blue', 3, 25);
这种方法被称为构造函数方式 。简要的说明一下,这段代码声明了一个Car类,oCar1和oCar2为其两个对象。看起来这段代码很是不错,但是注意那个this.showColor = function(){alert(this.color)};
this指代Car的一个对象,也就是说,每一个对象都有一个showColor方法,这势必会造成一种资源浪费。
再来看一种js构造类的示例:
- function Car(){
- }
- Car.prototype.color = "red";
- Car.prototype.doors = 4;
- Car.prototype.mpg = 23;
- Car.prototype.showColor = function(){
- alert(this.color);
- }
- var oCar1 = new Car();
- var oCar2 = new Car();
这种方法被称为原型方式 。该方法避免了showColor函数被每个对象都创建,而是所有Car类的对象共享这一个函数,然后在调用的时候,使用this关键字找到实例对象的color,这种方式也有问题,即color,doors和mpg被所有对象共享,如果一个对象修改了color那么其他的对象的color也会相应的改变。
那么显然将二者结合起来就好了:
- function Car(){
- this.color = sColor;
- this.doors = iDoors;
- this.mpg = iMpg;
- }
- Car.prototype.showColor = function(){
- alert(this.color);
- }
- var oCar1 = new Car();
- var oCar2 = new Car();
这种方式被称为混合的构造函数/原型方法 。
这个代码就没有什么问题了,那么动态原型方法 指的是什么呢?
我们先来看一段java代码:
- class Car {
- public String color = "red";
- public int doors = 4;
- public int mpg = 23;
- public Car(String color, int doors, int mpg){
- this.color = color;
- this.doors = doors;
- this.mpg = mpg;
- }
- public void showColor() {
- System.out.println(this.color);
- }
- }
这是和我们前面js构造出来的相似的一个java class.由此可见由于java超强的面向对象的机制,已经把这种属性和方法的区别为我们做好了,我们只需要将所有的方法写在class中,然后java处理好剩下的事情。
js也有一种几乎完全和这段java类似的方法-动态原型方法
- function Car(sColor,iDoors,iMpg){
- this.color = sColor;
- this.doors = iDoors;
- this.mpg = iMpg;
- if(typeof Car._initialized == "undefined"){
- Car.prototype.showColor = function(){
- alert(this.color);
- }
- Car._initialized = true.
- }
- }
这回看起来舒服多了吧,不过动态原型方法 在继承的时候有一个问题:
- function Polygon(iSides) {
- this.sides = iSides;
- if(typeof Polygon._initialized == "undefined"){
- Polygon.prototype.getArea = function(){
- return 0;
- }
- Polygon._initialized = true;
- }
- }
- function Triangle(iBase,iHeight){
- Polygon.call(this,3);
- this.base = iBase;
- this.height = iHeight;
- if(typeof Triangle._initialized == "undefined"){
- Triangle.prototype = new Polygon();
- Triangle.prototype.getArea = function(){
- return .5 * this.base * this.height;
- }
- Triangle._initialized = true;
- }
- }
- var tri1 = new Triangle(3,4);
- alert(tri1.getArea());
这段代码根本就跑不起来,也就是说当
- var tri1 = new Triangle(3,4);
执行的时候,程序会进入Triangle的构造函数中,然后依次执行,此时Triangle的这个对象已经被实例化了,所以当再次调用
- <strong>Triangle.prototype = new Polygon();</strong>
自然就会报错了。也就是说,动态原型方法 不适合与继承中子类的构造。
那么修改一下就可以了:
- function Polygon(iSides) {
- this.sides = iSides;
- this.type = "Polygon";
- if(typeof Polygon._initialized == "undefined"){
- Polygon.prototype.getArea = function(){
- return 0;
- }
- Polygon._initialized = true;
- }
- }
- function Triangle(iBase,iHeight){
- Polygon.call(this,3);
- this.base = iBase;
- this.height = iHeight;
- if(typeof Triangle._initialized == "undefined"){
- Triangle.prototype.getArea = function(){
- return .5 * this.base * this.height;
- }
- Triangle._initialized = true;
- }
- }
- Triangle.prototype = new Polygon();
- var tri1 = new Triangle(3,4);
- alert(tri1.getArea());
- alert(tri1.type);