javascript的四种继承方式

来源:互联网 发布:代码优化 编辑:程序博客网 时间:2024/05/18 00:42

原型继承

function Super() {  //自定义属性和方法}function Sub() {  //自定义属性和方法}Sub.prototype = new Super();Sub.prototype.constructor = Sub;

原型继承的优点是简单,缺点也很明显有两点,第一点、子类原型作为父类的实例时,用的是无参构造,也就是说子类构造函数的参数无法传递。第二点、当父类构造函数中使用引用数据类型时,子类实例对象的这个数据类型是共享的。

function Super() {  //自定义属性和方法  this.name = 'superName'  this.colors = ['r', 'g', 'b']}function Sub() {  //自定义属性和方法}Sub.prototype = new Super();Sub.prototype.constructor = Sub;var sub = new Sub();var sub2 = new Sub();sub.colors.push("OvO")sub.name = 'subName'console.log(sub)console.log(sub2)




借用构造函数继承

借用构造函数可以很好地解决上面的问题

function Super(name) {  //自定义属性和方法  this.name = name  this.colors = ['r', 'g', 'b']}function Sub(name) {  //自定义属性和方法  Super.apply(this, arguments)}var sub = new Sub('subName');var sub2 = new Sub('another');sub.colors.push("OvO")console.log(sub)console.log(sub2)



这种继承方式本质上只是借用了父类构造函数的作用域,优点同样是很简单,缺点则是子类实例对象无法继承父类原型的属性方法,而且无法共享同一个方法,因为实例对象全部借用构造函数私有化了,这问题就大了,如果你需要共享一个很大的数据集,每生成一个子类对象,你就重新创建一遍,很浪费内存,完全没有必要。

组合继承

上面两种继承明显是互补的,因此把它组合起来,问题不就解决了吗!

function Super(name) {  //自定义属性和方法  this.name = name  this.colors = ['r', 'g', 'b']}//把共享的属性方法用下面这种方式写出来,直接用字面量对象写会破坏继承链Super.prototype.sayName = function() {}function Sub(name) {  //自定义属性和方法  Super.apply(this, arguments)}Sub.prototype = new Super();Sub.prototype.constructor = Sub;Sub.prototype.sayColor = function() {}var sub = new Sub('subName');sub.colors.push("OvO")console.log(sub)

融合了借用构造函数和原型式继承的优点,较完美的实现了继承。缺点则是调用了两次父类构造函数,子类原型里被覆盖的属性也能说明被调用了两次,追求完美的同学可以用下面的寄生组合式继承。


寄生式组合继承

function inheritPrototype(subType,superType) {  //ES5新增方法  var prototype = Object.create(superType.prototype);  prototype.constructor = subType;  subType.prototype = prototype;}function Super(name) {  //自定义属性和方法  this.name = name  this.colors = ['r', 'g', 'b']}//把共享的属性方法用下面这种方式写出来,直接用字面量对象写会破坏继承链Super.prototype.sayName = function() {}function Sub(name) {  //自定义属性和方法  Super.apply(this, arguments)}inheritPrototype(Sub, Super);Sub.prototype.sayColor = function() {}var sub = new Sub('subName');sub.colors.push("OvO")console.log(sub)




不理解inhetirPrototype函数的同学可以看一下下面两行代码,起到的效果是一样的

Sub.prototype.__proto__ = Super.prototype;Sub.prototype.constructor = Sub;

结语

总结下来其实也很简单,就是让子类原型的原型指针指向父类原型,私有属性写在构造函数里,公有属性写在原型里。
有兴趣的同学可以去实现在父类和子类中间桥接一个类,更能帮助理解!
如果有不正确的地方,欢迎大家拍砖!

原创粉丝点击