JS 实现继承的几种方式

现在有parent、child两个函数,child函数的实例想要访问parent函数的属性和方法(child想要继承parent)。

1、原型链继承

缺点:有引用的值共享的问题

即当parent某个属性是引用数据类型的时候,child实例如果修改了这个属性的内容则其他的child实例中这个属性也会一起改变(正常来说应该是互不干扰的,原始数据类型属性就是互不干扰的)

function parent(){
    this.data = '我是parent'
}

function child(){}

child.prototype = new parent()

var fun = new child()

console.log(fun.data)

2、构造函数继承

通过在child函数中独立执行parent( 此时parent的this指向window ),然后通过call方法改变parent的指向指向child实例( parent.call(this) ),这样new出来的child实例就能访问到parent中的属性和方法了。这种方法就称为构造函数继承。

缺点:使用这种方法child实例没有办法拿到parent函数原型上的属性和方法。

function parent(){
    this.data = '我是parent'
}

parent.prototype.say = function(){
    console.log("我是parent原型")
}

function child(){
    parent.call(this)
}

var fun = new child()

console.log(fun.data)        // 输出“我是parent”
fun.say()                    // 此处报错

3、组合继承(构造函数+原型链)

这个方法是结合了上述的两个方法:

  • 用构造函数继承中的child函数独立执行parent来解决原型链继承的引用值共享问题
  • 用原型链继承中child函数的原型指向parent的实例来解决构造函数中child实例无法访问parent原型上属性和方法的问题。

 缺点:new了两次parent,会产生了属性与方法重叠的问题。

function parent(){
    this.data = '我是parent'
}

parent.prototype.say = function(){
    console.log("我是parent原型")
}

function child(){
    parent.call(this)
}

child.prototype = new parent()

var fun = new child()

console.log(fun.data)
fun.say()

 4、寄生组合继承(经典继承)

(第三种方法)组合继承:无论什么情况下,都会调用两次父类的构造函数。寄生组合式继承就解决了上述问题,被认为是最理想的继承方式。

function parent(){
    this.data = '我是parent'
}

parent.prototype.say = function(){
    console.log("我是parent原型")
}

function child(){
    parent.call(this)
}

child.prototype = Object.create(parent.prototype)

var fun= new child()

console.log(fun.data)
fun.say()

5、原型式继承

原型式继承是一种基于已有对象创建新对象的继承方式,适用于简单对象的继承。在 JavaScript 中可以使用 Object.create 方法来实现原型式继承。

// 原型对象
var parent = {
  name: 'parent',
  age: 30,
  say: function () {
    return '我是' + this.name
  }
}

// 基于原型对象创建新对象
var child= Object.create(parent)

child.name = 'Alice'   // 修改属性值
child.age = 25         // 修改属性值

console.log(child.say()) // 输出 "我是 Alice"

6、es6的extends类继承 

 child类通过extends继承了parent类的属性和方法。

class Parent {
  constructor(name) {
    this.name = name
  }
  // 原型方法
  // 即 Parent.prototype.getName = function() { }
  // 下面可以简写为 getName() {...}
  getName = function () {
    console.log('Parent:', this.name)
  }
}
class Child extends Parent {
  constructor(name, age) {
    // 子类中存在构造函数,则需要在使用“this”之前首先调用 super()。
    super(name)
    this.age = age
  }
}
const asuna = new Child('Asuna', 20)
asuna.getName() // 成功访问到父类的方法

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值