JavaScript 继承方式
关于继承可以朴素的理解为,通过继承,子类可以复用父类的方法,以达到代码重用。JavaScript 可用多种方式模拟继承,本文先举例介绍各种方法,后对比分析优缺点。
在 JavaScript 中,构造函数也和普通的函数一样,可以被赋值和调用,对象冒充通过此原理来模拟继承。
对象冒充和基于原型的方式都可以让子类复用父类的代码以模拟继承,但这两种方法均各有利弊。
利用对象冒充,可以方便的实现多继承,只需要对所有需要继承的父类重复进行赋值流程便可。但这样却有着有明显的性能缺陷,因为在利用对象冒充模拟继承时,每个实例都会拥有一份父类成员变量和方法的副本,而成员方法只是一段对变量操作的可执行文本区域而已,这段区域不用为每个实例复制一份,所有的实例均可共享,这就造成了对内存资源的极度浪费。并且对象冒充也无法继承 prototype 域的变量和方法。
而基于原型的继承则可以使子类拥有一条完整的原型链,并且所有子类实例的原型都指向同一引用,相对于对象冒充,可极大的节省内存开销。但基于原型继承的缺陷也相当明显,就是父类的构造函数不能有参数,因为对子类 prototype 域的修改需在声明子类对象之后才能进行,而用子类构造函数的参数去初始化父类构造函数的属性是无法实现的。
因此可以结合二者的优点,采用混合的方式模拟继承,即用对象冒充的方式给属性赋值,用原型链的方式继承方法,示例代码如下:
Function ClassA(name){ this.name = name; } ClassA.prototype.sayHello = function(){ alert("Hello, " + this.name); } Function ClassB(name,time){ ClassA.call(this, name); this.time = time; } ClassB.prototype = new ClassA(); ClassB.prototype.sayGoodbye = function(){ alert("Goodbye " + this.name + ",it's " + this.time + " now !"); } var objA = new ClassA("Tom"); var objB = new ClassB("Jerry","11:30am"); objA. sayHello();// output is: "Hello, Tom" objB.sayHello(); // output is: "Hello, Jerry" objB.sayGoodbye();//output is: "Goodbye Jerry,it ’ s 11:30am now !"