总结js继承的几种方式(下)

273 阅读2分钟

这是我参与11月更文挑战的第28天,活动详情查看:2021最后一次更文挑战

继承

接着上篇文章讲的几种继承方式(原型链继承,构造函数继承,组合继承),这篇文章继续讲剩下的继承方式。

原型式继承

原型式继承,通过定义一个普通函数,然后把继承的对象通过参数传入,在普通函数内部,新建一个构造函数,把传入的继承对象赋值给它的原型对象,最后返回这个构造函数的实例,最后达到继承的目的。

function fn (o) {
  function Fn() {}
  Fn.prototype = o
  return new Fn()
}

var o = {
  name: 'a'
}

var a = fn(o)
console.log(a.name) // a

这个原型式继承可以根据传入的对象不同,然后实例继承的就不一样。

es5新增了Object.create方法,和原型式继承的逻辑基本类似。

var o = {
  name: 'a'
}
var a = Object.create(o)
console.log(a.name) // a

寄生式继承

寄生式继承,是在原型式继承的基础上,又多了一个普通函数,参数是把继承的对象传入,然后在内部利用原型式继承返回实例,然后还可以给实例本身加上属性/方法。 /方法。

function fn (o) {
  function Fn() {}
  Fn.prototype = o
  return new Fn()
}

function wrap (o) {
    var instance = fn(o)
    instance.name = 'aa'
    instance.getName = function() {
      return this.name
    }
    return instance
}

var o = {
  name: 'a'
}
var a = wrap(o)
console.log(a.name) // aa
console.log(a.getName()) // aa

寄生组合式继承

寄生组合式继承这个是结合寄生式继承和构造函数继承形成的继承,通过构造函数继承父类本身的属性/方法,通过寄生式继承父类原型的上的属性/方法。

function Son () {
  Father.call(this)
}
function Father () {
  this.name = 'father'
}
Father.prototype.getName = function () {
    return this.name
}
function fn (o) {
  function Fn() {}
  Fn.prototype = o
  return new Fn()
}
function wrap (son, father) {
  var prototype = fn(father.prototype)
  son.prototype = prototype
  son.constructor = son
}

wrap(Son, Father)
var p = new Son()
console.log(p) // Son {name: 'father',...}
console.log(p.getName())

es6的继承

es6新增了类class,class的继承是通过extendssuper两个关键字来完成。

class Father {
 constructor (name, age) {
   this.name = name
   this.age =age
 }
 getName () {
   return this.name
 }
}
class Son extends Father {
 constructor (...args) {
   super(...args)
 }
}

var p = new Son('答案cp3', 18)
console.log(p.getName()) // 答案cp3
console.log(p.age) // 18

可以看到实例继承了父类的name和age字段,传入参数直接生效。

目前还是推荐可以使用es6的class,可读性强,操作方便。

更详细的class的继承可以看我之前这篇文章