JavaScript是基于对象的语言,以对象为基础,以函数为模型,以原型为继承机制的开发模式。下面主要介绍一下类继承。其设计方法为在子类中执行父类的构造函数。在JavaScript中实现类的继承,要考虑和设置以下三点:
- 在构造函数B的结构体内,使用函数call()调用构造函数A,把B的参数x传递给调用函数,让B能够继承A的所有属性和方法,即A.call(this, x);语句行。
- 在构造函数A和B之间建立原型链,即B.prototype = new A();语句行。在JavaScript中每个构造类都有一个名为prototype的属性,该属性指向一个对象。在访问对象的某个成员时,如果在当前域中没有找到,则会根据prototype属性指向的对象并沿着这个原型链不断向上查找,直到找到为止。因此,为了实现类之间的继承,必须保证它们是原型链上的上下级关系,即设置子类的prototype属性指向超类的一个实例即可。
- 恢复B的原型对象的构造函数,即B.prototype.constructor = B;语句行。当定义构造函数时,其原型对象(prototype属性值)默认是Object类型的一个实例,其构造器(constructor属性值)会被默认设置为该构造函数本身。如果改动prototype属性值,使其指向另一个对象,那么新对象就不会拥有原来的constructor属性值,所以必须重新设置constructor属性值。
//基类 function A(x) { //构造函数A this.get1 = function() { //本地方法,获取参数值 return x; } } A.prototype.has = function() { //原型方法,判断get1()方法返回值是否为0(false) return ! (this.get1() == 0); } //超类B function B() { //构造函数B var a = []; //私有数组a a = Array.apply(a, arguments); //把参数数组传入数组a中 A.call(this, a.length); //在当前对象中调用A类,并把参数数组长度传递给它 this.add = function() { //本地方法,把参数数组补加到数组a中,并返回 return a.push.apply(a, arguments); } this.geta = function() { //本地方法,返回数组a return a; } } B.prototype = new A(); //设置B类的原型为A的实例,从而建立原型链 B.prototype.constructor = B; //恢复B类原型对象的构造器 B.prototype.str = function() { return this.geta().toString(); } //子类C function C() { //构造函数 B.apply(this, arguments); //在当前对象中调用B类,并把参数数组长度传递给它 this.sort = function() { //本地方法,以字符顺序对数组进行排序 var a = this.geta(); //获取数组的值 a.sort.apply(a, arguments); // 调用数组排序方法sort()对数组进行排序 } } C.prototype = new B(); //设置C类原型为B类的实例,从而建立原型链 C.prototype.constructor = C; //恢复C类原型对象的构造器 //超类B的实例继承A的成员 var b =new B(1,2,3,4); //实例化B类 alert(b.get1()); //返回4,调用A类的方法get1() alert(b.has()); //返回true,调用A类的方法has() //子类C的实例继承类B和类A的成员 var c = new C(30,10,20,40); //实例化C类 c.add(6,5); //调用B类方法add(),补加数组 alert(c.geta()); //返回数组30,10,20,40,6,5 c.sort(); //排序数组 alert(c.geta()); //返回数组10,20,30,40,5,6 alert(c.get1()); //返回4,调用A类的方法get1() alert(c.has()); //返回true,调用A类的方法has() alert(c.str()); //返回10,20,30,40,5,6
代码很长,但是大体的思路很简单,设计类C继承类B,而类B又继承了类A。这三个类之间的继承关系是通过在子类中调用父类的构造函数来维护的。结合在开头我们说的那三个原则就能顺下来了。