面试高频手写题009-实现类的继承

实现类的继承,目前常见的有四种方式:

  • ES6继承

  • 借助call实现继承

  • 借助原型链实现继承

  • 组合式继承

一、ES6继承(非常推荐)

// ES6继承
class Parent {
  constructor(name) {
    this.name = name
  }
  say() {
    console.log(this.name + ` say`);
  }
  play() {
    console.log(this.name + ` play`);
  }
}

class Child extends Parent {
  constructor(name, age) {
    super(name)
    this.age = age
  }
}

// 测试用例
let o1 = new Child('zhangsan', 18)
console.log(o1, o1.name, o1.age)
o1.say()
o1.play()

二、借助call实现继承

存在问题:子类只能继承父类的属性,不能继承父类原型上的方法

// 借助call实现继承
// 存在问题:子类只能继承父类的属性,不能继承父类原型上的方法
function Parent(name) {
  this.name = name
}

Parent.prototype.say = function() {
  console.log(this.name + ` say`);
}
Parent.prototype.play = function() {
  console.log(this.name + ` play`);
}

function Child(name, age) {
  Parent.call(this, name)
  this.age = age
}

// 测试用例
let o1 = new Child('zhangsan', 18)
console.log(o1, o1.name, o1.age)  // Child { name: 'zhangsan', age: 18 } zhangsan 18
// o1.say() // TypeError: o1.say is not a function

三、借助原型链实现继承

存在问题:

  1. 虽然子类可以访问父类的属性和方法,但是数据属性是所有实例共享的,修改容易造成混乱;

  1. 子类实例的构造函数是Parent

// 借助原型链实现继承
// 存在问题:数据属性共享,修改容易造成混乱;子类实例的构造函数是Parent
function Parent() {
    this.name = 'parent'
    this.lists = [1, 2, 3]
  }
  
  Parent.prototype.say = function() {
    console.log(this.name + ` say`);
  }
  Parent.prototype.play = function() {
    console.log(this.name + ` play`);
  }
  
  function Child(age) {
    this.age = age
  }

  Child.prototype = new Parent()
  
  // 测试用例
  let o1 = new Child(18)
  let o2 = new Child(20)
  console.log(o1, o1.lists, o1.age)  // Parent { age: 18 } [ 1, 2, 3 ] 18
  console.log(o2, o2.lists, o2.age)  // Parent { age: 20 } [ 1, 2, 3 ] 20
  o2.lists.push(88)
  console.log(o1, o1.lists, o1.age)  // Parent { age: 18 } [ 1, 2, 3, 88 ] 18
  console.log(o2, o2.lists, o2.age)  // Parent { age: 20 } [ 1, 2, 3, 88 ] 20

四、组合式继承

存在问题:

  1. 父类构造函数会执行两次

  1. 子类实例的构造函数是Parent

// 组合式继承:call+原型链
// 存在问题:父类构造函数会执行两次;子类实例的构造函数是Parent
function Parent() {
    this.name = 'parent'
    this.lists = [1, 2, 3]
  }
  
  Parent.prototype.say = function() {
    console.log(this.name + ` say`);
  }
  Parent.prototype.play = function() {
    console.log(this.name + ` play`);
  }
  
  function Child(age) {
    Parent.call(this)  // 父类构造函数第二次执行
    this.age = age
  }

  Child.prototype = new Parent() // 父类构造函数第一次执行
  
  // 测试用例
  let o1 = new Child(18)
  let o2 = new Child(20)
  console.log(o1, o1.lists, o1.age)  // Parent { name: 'parent', lists: [ 1, 2, 3 ], age: 18 } [ 1, 2, 3 ] 18
  console.log(o2, o2.lists, o2.age)  // Parent { name: 'parent', lists: [ 1, 2, 3 ], age: 20 } [ 1, 2, 3 ] 20
  o2.lists.push(88)
  console.log(o1, o1.lists, o1.age)  // Parent { name: 'parent', lists: [ 1, 2, 3 ], age: 20 } [ 1, 2, 3 ] 20
  console.log(o2, o2.lists, o2.age)  // Parent { name: 'parent', lists: [ 1, 2, 3, 88 ], age: 20 } [ 1, 2, 3, 88 ] 20

组合式继承优化版本:

// 组合式继承优化版本:解决了一般组合式继承存在的问题
function Parent() {
  this.name = 'parent'
  this.lists = [1, 2, 3]
}

Parent.prototype.say = function() {
  console.log(this.name + ` say`);
}
Parent.prototype.play = function() {
  console.log(this.name + ` play`);
}

function Child(age) {
  Parent.call(this)
  this.age = age
}

Child.prototype = Object.create(Parent.prototype)
Child.prototype.constructor = Child;

// 测试用例
let o1 = new Child(18)
let o2 = new Child(20)
console.log(o1, o1.lists, o1.age)  // Child { name: 'parent', lists: [ 1, 2, 3 ], age: 18 } [ 1, 2, 3 ] 18
console.log(o2, o2.lists, o2.age)  // Child { name: 'parent', lists: [ 1, 2, 3 ], age: 20 } [ 1, 2, 3 ] 20
o2.lists.push(88)
console.log(o1, o1.lists, o1.age)  // Child { name: 'parent', lists: [ 1, 2, 3 ], age: 18 } [ 1, 2, 3 ] 18
console.log(o2, o2.lists, o2.age)  // Child { name: 'parent', lists: [ 1, 2, 3, 88 ], age: 20 } [ 1, 2, 3, 88 ] 20
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值