JS 常见的 6 种继承方式

文章详细介绍了JavaScript中五种常见的继承实现方式:原型链继承、构造函数继承、组合继承、原型式继承、寄生式继承,以及它们的特点和潜在问题。例如,原型链继承可能导致实例间属性共享,而构造函数继承无法继承方法。组合继承结合了两者优点,但仍有冗余。寄生式继承用于创建对象副本并添加新方法。最后提到了寄生组合式继承,它能更有效地避免上述问题。
第一种:原型链继承

 

原型链继承是比较常见的继承方式之一,其中涉及的构造函数、原型和实例,三者之间存在着一定的关系,即每一个构造函数都有一个原型对象,原型对象又包含一个指向构造函数的指针,而实例则包含一个原型对象的指针。

function one1() {
  this.name = '科技改变世界'
  this.array = [1, 2, 3]
}

function two() {
  this.type = '名字'
}

two.prototype = new one1()

let two2= new two()

console.log(two2)

上面的代码看似没有问题,虽然父类的方法和属性都能够访问,但其实有一个潜在的问题

  let c1 = new one1();

  let c2 = new one1();

  c1.play.push(4);

  console.log(c1.play, c2.play);

明明只改变了 c1 的 play 属性,为什么 c2 也跟着变了呢?原因很简单,因为两个实例使用的是同一个原型对象。它们的内存空间是共享的,当一个发生变化的时候,另外一个也随之进行了变化,这就是使用原型链继承方式的一个缺点。

第二种:构造函数继承(借助 call)
 // 借用构造函数实现的继承,只能继承属性,不能继承方法
function one1(name,sex){
    this.name = name
    this.sex = sex
}
function tow2(sco,name,sex){
    // 学生对象实例中的this指向实例对象
    // tow2构造函数通过call方法,改变this指向
    one1.call(this,name,sex)
    this.sco = sco
}
// 创建学生对象
let stu1 = new tow2(100,'kk','man')
let stu2 = new tow2(98,'hh','female')
// stu1.sleep() 
//  stu1.sleep is not a function
console.log(stu1);
console.log(stu2);

 第三种:组合继承(前两种组合)

// 组合继承:改变原型指向和和借用构造函数实现继承组合使用
// 人的构造函数
function one1(name,sex){
    this.name = name
    this.sex = sex
}

function tow2(sco,name,sex){
    // 学生对象实例中的this指向实例对象
    // one1构造函数通过call方法,改变this指向,实现Stu继承one1的属性
    one1.call(this,name,sex)
    this.sco = sco
}

// 改变Stu原型指向,实现Stu继承one1的方法
tow2.prototype = new one1()
tow2.prototype.constructor = tow2

let stu1 = new Stu(100,'kk','man')
let stu2 = new Stu(98,'hh','female')

console.log(stu1);
console.log(stu2);
console.log(stu1.sleep == stu2.sleep)
第四种:原型式继承
let one = {
  name: '科技改变世界',
  friends: ['p1', 'p2', 'p3'],
  getName: function () {
    return this.name
  },
}

let person = Object.create(one)

person.name = '科技'
person.friends.push('p4')

let person2 = Object.create(one)
person2.friends.push('p5')

console.log(person.name)
console.log(person.name === person.getName())
console.log(person2.name)
console.log(person.friends)
console.log(person2.friends)
第五种:寄生式继承
let parent5 = {
  name: 'parent5',
  friends: ['p1', 'p2', 'p3'],
  getName: function () {
    return this.name
  },
}

function clone(original) {
  let clone = Object.create(original)
  clone.getFriends = function () {
    return this.friends
  }
  return clone
}

let person = clone(parent5)

console.log(person.getName())
console.log(person.getFriends())
第六种:寄生组合式继承
function Parent6() {
  this.name = 'parent6'
  this.play = [1, 2, 3]
}
Parent6.prototype.getName = function () {
  return this.name
}

function Child6() {
  Parent6.call(this)
  this.friends = 'child5'
}

function clone(parent, child) {
  child.prototype = Object.create(parent.prototype)
  child.prototype.constructor = child
}

clone(Parent6, Child6)

Child6.prototype.getFriends = function () {
  return this.friends
}

let person = new Child6()

console.log(person)
console.log(person.getName())
console.log(person.getFriends())

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值