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中的非原型属性和方法)会被覆盖掉

 

好吧,以上观点和大部分代码,都来自《JavaScript高级程序设计》作者:Nicholas C.Zakas 译者:曹力 张欣等

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