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 译者:曹力 张欣等

浙公网安备 33010602011771号