继承
继承是面向对象编程中很重要的一个概念,继承分两种:接口继承和实现继承。接口继承是继承签名,实现继承是继承属性和方法,因为js函数没有签名,所以在js中无法实现接口继承。js中只能实现继承,下面就总结一下js中几种实现继承方式,以及对应的优缺点。
1、原型链继承
function SuperType() { this.color = ["yellow", "green", "blue"]; } SuperType.prototype.getSuperValue = function() { return this.color; } function SuberType() { this.subproperty = false; } SuberType.prototype = new SuperType(); SuberType.prototype.getSuberValue = function() { return this.subproperty; } let instance1 = new SuberType(); console.log(instance1.color); //["yellow", "green", "blue"] console.log(instance1.getSuperValue()); //["yellow", "green", "blue"] instance1.color.push("pink"); console.log(instance1.color); //["yellow", "green", "blue", "pink"] let instance2 = new SuberType(); console.log(instance2.color); //["yellow", "green", "blue", "pink"]
讯享网
从上述代码的执行,我们可以看出子类SuberType继承了父类SuperType的属性和方法,但是缺点我们可以很明显的看到SuberType的实例修改color属性相互影响,这是因为执行SuberType.prototype = new SuperType()这行代码,就相当于给SuberType.prototype添加了color的属性,SuberType.prototype.color = [“yellow”, “green”, “blue”],以至于所有SuberType的实例都共享了这个color属性。原型链实现继承还有一个问题就是在创建子类实例的我时候无法向父类型的构造函数中传递参数,总结原型链实现继承的优缺点如下。
2、借用构造函数
讯享网 function SuperType(name) { this.color = ["yellow", "green", "blue"]; this.name = name; } SuperType.prototype.getSuperValue = function() { return this.color; } function SuberType(name) { SuperType.call(this,name) this.subproperty = false; } let instance1 = new SuberType("hello world"); console.log(instance1.color); //["yellow", "green", "blue"] console.log(instance1.name); //hello world try { console.log(instance1.getSuperValue()); }catch(e) { console.log(e) }//TypeError: instance1.getSuperValue is not a function instance1.color.push("pink"); console.log(instance1.color); //["yellow", "green", "blue", "pink"] let instance2 = new SuberType(); console.log(instance2.color); //["yellow", "green", "blue"]
从上述代码的执行我们可看出,借助构造函数实现继承解决了原型链实现继承的缺陷,子类的实例修改引用类型不会相互影响了,子类的实例也可以向父类的构造函数传递参数了,但是缺点也很明显,子类的实类无法继承父类原型上的属性和方法。还有一个缺点就是借助构造函数模式,方法都在构造函数中定义,无法实现函数的复用,总结一下借助构造函数实现继承的优缺点。
3、组合继承
function SuperType(name) { this.color = ["yellow", "green", "blue"]; this.name = name; } SuperType.prototype.getSuperValue = function() { return this.color; } function SuberType(name) { SuperType.call(this,name); //第二次调用SuperType( ) this.subproperty = false; } SuberType.prototype = new SuperType(); //第一次调用SuperType( ) SuberType.constructor = SuberType; let instance1 = new SuberType("hello world"); console.log(instance1.color); //["yellow", "green", "blue"] console.log(instance1.name); //hello world console.log(instance1.getSuperValue()); instance1.color.push("pink"); //["yellow", "green", "blue"] console.log(instance1.color); //["yellow", "green", "blue", "pink"] let instance2 = new SuberType(); console.log(instance2.color); //["yellow", "green", "blue"]
从上述代码中我们可以看出,组合继承的思路是使用原型链实现对原型属性和方法的继承,通过构造函数实现对实例属性的继承,这样既通过在原型上定义方法实现函数的复用,又能保证每个实例都有自己的属性,缺点我们也可以看出,无论什么情况下,都会调用两次父类构造函数,第一次是在创建子类实例的时候,另一次是在子类构造函数的内部。子类最终会包含父类的全部实例属性,但是,我们在调用子类构造函数的时候又重写了这些属性。下面我们就总结一下组合继承的优缺点。
4、寄生组合式继承
讯享网 function inheritPrototype(subType, superType) { let prototype = Object(superType.prototype); prototype.constructor = subType; subType.prototype = prototype; } function SuperType(name) { this.color = ["yellow", "green", "blue"]; this.name = name; } SuperType.prototype.getSuperValue = function() { return this.color; } function SuberType(name) { SuperType.call(this,name) this.subproperty = false; } inheritPrototype(SuberType, SuperType); let instance1 = new SuberType("hello world"); console.log(instance1.color); //["yellow", "green", "blue"] console.log(instance1.name); //hello world console.log(instance1.getSuperValue()); //["yellow", "green", "blue"] instance1.color.push("pink"); console.log(instance1.color); //["yellow", "green", "blue", "pink"] let instance2 = new SuberType();
从上述代码中我们可以看出寄生组合式继承的基本思路是不通过调用父类构造函数给子类原型赋值,而是取得父类原型的一个副本,inheritPrototype()函数实现了寄生式组合继承的核心。这个函数接收两个参数:子类构造函数和父类构造函数。在函数的内部,先是创建父类原型的一个副本。然后给返回的prototype 对象设置 constructor 属性,解决由于重写原型导致默认 constructor 丢失的问题。最后将新创建的对象赋值给子类型的原型。寄生组合式继承是相对完美实现继承方式,弥补了上面几种实现继承的缺点。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/74130.html