javascript中类的编写规范和继承方式

最近正在学习一些跨平台的移动框架,像sencha touch和jquery mobile,需要用到js这块的很多技术,其中对于类表示一直用起来很生疏,于是找了一些这方面的资料,总算是搞明白了

 

一、类的规范

js中的类声明方式很简单也很混乱,主要是这几种简单的方式 

1.构造函数方式

1 function car(val)  {
2      var x = 5;  //私有变量
3       this.color = val;  //通过对象.color访问
4       this.run = function() {  //同上,通过对象访问
5           alert("run");
6       }
7  }

这种方式可以实现面向对象中类和对象的功能,但是会有性能上的问题,每次 new car(3) 都会创建一次这个对象对应的的属性和方法,每个对象的属性不同符合规范,但是每次都为对象创建独立的函数版本,这样毫无意义,浪费资源

 

2.原型方式

 1   function car() {
 2   
 3   }
 4   
 5   car.prototype.color = 3;
 6   car.prototype.run = function() {
 7       alert("run");
 8   }
 9   
10  var car1 = new car();
11  var car2 = new car(); 

这种方式通过把属性和函数都放到原型中来构建类,虽然解决了函数的重复创建问题,但是弊端更加明显,由于属性在原型中,导致所有对象都共用同一个属性(即修改car1的color,car2的color也会改变),而且这种方式不能传递参数初始化属性

 

3.混合构造函数/原型方式

1  function car(val) {
2      this.color = val;
3  }
4  car.prototype.run = function() {
5     alert("run");
6  }

这种方式在原型中声明函数,在构造函数中创建属性,可以在创建对象的时候初始化属性,而且不会重复创建函数,是推荐的方法

 

4.但是有些人看到上面的方法很不爽,因为函数写在function外面感觉很散,于是有人把上面的东东换了种方式

 1  function car(val) {
 2       this.color = val;
 3      
 4       if(typeof car._initialized == "undefined") {
 5             car.prototype.run = function () {
 6                  alert("run");
 7             }
 8   
 9            car._initialized = true;
10      }
11  }

这样函数就在创建对象的时候被写到原型里,但是偶还是看第3种比较顺眼

其他的肥猪流方式,都不太靠谱,偶就不记了

 

二、继承

好吧,继承也有很多乱七八糟的方式,有下面这几种

1.对象冒充

 1   function classA(sColor) {
 2      this.color = sColor;
 3      this.sayColor = function () {
 4        alert(this.color);
 5      }
 6   }
 7   
 8   //从classA中继承
 9   function classB(sColor,sName) {
10      classA.call(this,sColor); //call方法将classA中的this替换成了classB中的this(这点不懂最好google一下),将classA的构造函数中的属性和函数加载到calasB中
11  
12      this.name = sName;
13      this.sayName = function() {
14               alert(this.name);
15     }
16  }

这种方式可以实现靠谱的继承,但是问题也很明显,就是原型中的函数和属性它是继承不来的,而且要求成员函数必须在构造函数中,用this的方式定义

 

2.原型链

这又是走向了另一个极端,但是值得一看

 1   function classA() {
 2   
 3   }
 4   classA.prototype.color = "red";
 5   classA.prototype.sayColor = function() {
 6         alert(this.color);
 7   };
 8   
 9   function classB() {
10  
11  }
12  classB.prototype = new classA(); //这句将A中的构造函数中的属性方法和原型中的属性方法都加载到classB中
13  classB.prototype.name = "";
14  classB.prototype.sayName = function() {
15       alert(this.name);
16  }

这种方式能将classA中的所有属性和方法都放到classB的原型中,但是原型链有一个很大的问题就是这句classB.prototype = new classA();中的classA()是不允许传递参数的,这样就无法在创建对象的时候初始化属性,而且将属性放到原型中也不符合前面所说的规范

 

3.混合方式

这个是推荐方式

 1  function classA(sColor) {
 2        this.color = sColor;
 3   }
 4   classA.prototype.sayColor = function() {
 5        alert(this.color);
 6   }
 7   
 8   function classB(sColor,sName) {
 9        classA.call(this.sColor);
10        this.name = sName;
11  }
12  classB.prototype = new classA();
13  classB.prototype.sayName = function() {
14        alert(this.name);
15  };

这里面classB.prototype = new classA();将classA中的所有属性和方法都加载到classB的原型中,而classA.call()则将classA的非原型属性和方法加载到classB中,根据原型与成员变量的优先级规则,classB原型中加载的多余的属性方法(即classA中的非原型属性和方法)会被覆盖掉

posted @ 2012-06-07 19:23  炉猫  阅读(161)  评论(0)    收藏  举报