js基础之继承

js继承:是指一个对象可以继承另一个对象的属性和方法,以便利用现有的代码来创建新的对象。
在JavaScript中,继承主要有以下几种常见的实现方式

  1. 通过原型链继承
  2. 构造函数继承
  3. 组合继承(即原型链继承+构造函数继承)
  4. 寄生组合继承
  5. es6类的继承

下面就这五种继承,分别介绍一下

原型链继承

原理

首先要知道原型链是什么?如下图示,理解一下

原型链
原型继承的原理就是 把子类的原型指向父类的实例

示例

// 定义一个People构造函数
function People() {
  this.head = 1
  this.leg = 2
  this.hand = 2
  this.ary = ['张三', '李四']
  this.say = function () {
    console.log('说废话')
  }
}
// 子类1
function Man() {}
// 子类2
function Woman() {}
// 子类1继承
Man.prototype = new People()
Man.prototype.contructor = Man
// 子类2继承
Woman.prototype = new People()
Woman.prototype.contructor = Woman
// 子类的原型上添加一个test方法
Man.prototype.test = function () {}
const man1 = new Man()
const man2 = new Man()
const woman1 = new Woman()
man1.ary.push('王五')
console.log(man1)
console.log(man2)
console.log(woman1.ary)

在这里插入图片描述

原理

综上,原型继承存在两个问题

  1. 父类中的所有引用类型的属性(比如上面的ary),会被子类中所有的实例(如man1,man2)共享(除非去创建多个子类,不同子类实例之间不会影响)
  2. 子类实例不能给父类构造函数传参

构造函数继承

原理

在子构造函数中使用call或apply方法调用父类构造函数,将父类的属性和方法复制给子类,从而实现继承。

示例

// 定义一个People构造函数
function People() {
  this.head = 1
  this.leg = 2
  this.hand = 2
  this.ary = ['张三', '李四']
  this.say = function () {
    console.log('说废话')
  }
}
// 构造函数原型上添加方法
People.prototype.test = function () {
  console.log(123)
}
// 构造函数继承
function Man() {
  People.call(this)
}
let man1 = new Man()
let man2 = new Man()
man1.ary.push('王五')

console.log(man1, man2)
console.log(man1.test()) // 是否存在父构造函数原型上的方法?不存在

在这里插入图片描述

问题

无法继承父构造函数原型上的属性或方法

组合继承

原理

原型继承和构造函数继承的结合
解决了原型继承和构造函数继承存在的问题,它可以继承父类原型链上的属性和方法,同时也可以避免子类实例共享父类实例属性的问题,也可以在调用父类构造函数时传递参数

示例

// 定义一个People构造函数
function People() {
  this.head = 1
  this.leg = 2
  this.hand = 2
  this.ary = ['张三', '李四']
  this.say = function () {
    console.log('说废话')
  }
}
// 构造函数原型上添加方法
People.prototype.test = function () {
  console.log(123)
}
// 构造函数继承
function Man() {
  People.call(this) // 在这里可以调用父类构造函数传参  People.call(this,...args) 
}
// 原型继承
Man.prototype = new People()
let man1 = new Man()
let man2 = new Man()
man1.ary.push('王五')
console.log(man1.test()) // 123
console.log(man1, man2)

在这里插入图片描述

问题

虽然解决了原型继承和构造函数继承存在的问题
但是,仍存在问题:
父类构造函数被调用了两次,一次是在子类构造函数中,另一次是在子类原型对象中,
可能存在一定的性能影响。

寄生组合继承

原理

寄生组合式继承其实就是寄生继承+组合继承

什么是寄生继承呢?
寄生继承的原理就是创建一个新对象,然后将要继承的对象作为新对象的原型,然后再为新对象添加新的属性和方法,从而实现继承。

// 寄生继承
// 其实就是Object.create()的原理
function createObject(obj) {
  function F() {} // 创建一个函数
  F.prototype = obj; // 将函数的原型指向新对象
  return new F(); // 返回函数的实例对象
}

示例

// 定义一个People构造函数
function People() {
  this.head = 1
  this.leg = 2
  this.hand = 2
  this.ary = ['张三', '李四']
  this.say = function () {
    console.log('说废话')
  }
}
// 构造函数原型上添加方法
People.prototype.test = function () {
  console.log(123)
}
// 构造函数继承
function Man() {
  People.call(this)
}
// 不直接去原型继承了
// Man.prototype = new People()
// 而是创建一个新函数
const Fn = function () {}
Fn.prototype = People.prototype
Man.prototype = new Fn()

let man1 = new Man()
let man2 = new Man()
man1.ary.push('王五')
console.log(man1.test())
console.log(man1, man2)

问题

相对完美的一种继承方式,解决了上面存在的问题

es6类继承

原理

在ES6中,通过定义一个类来创建一个对象,然后通过extends和super关键字来继承另一个类的属性和方法。

示例

class Parent {
  constructor(name,age){
    this.name = name
    this.age = age
  }
  sayName(){
    console.log(this.name);
  }
}
// extends 继承父类
class Child extends Parent{
  constructor(name,age,gender){
    // 继承属性
    super(name,age)
    this.gender = gender
  }
  sayGender(){
    console.log(this.gender);
  }
}
const ming = new Child('ming',18,'男')
const ming1 = new Child('ming1',19,'女')
// ming.sayGender()
// ming.sayName()
console.log(ming.name);
console.log(ming1.name);
console.log(ming.age);
console.log(ming1.age);
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值