javascript继承

本文详细探讨了JavaScript中的四种继承方式:原型继承、借用继承、组合继承和拷贝继承。每种方式都有其优缺点,例如原型继承能复用方法但无法传参,借用继承解决了传参问题但方法不复用。组合继承综合了两者的优点,而拷贝继承则提高了方法查找效率。在实际开发中,开发者应根据项目需求选择合适的继承策略。
摘要由CSDN通过智能技术生成

原型继承

优点:可以继承原型中的方法

缺点:1.实例属性虽然有,但是无法传参(跟没有一样);
           2. 子类实例对象共享了父类构造函数的引用属性

  function Animal(name, age) {
    this.name = name
    this.age = age
    this.other = {
      age: 1
    }
    this.eat = function() {
      console.log('品味美食')
    }
  }

  Animal.prototype.say = function () {
    console.log('hello');
  }

  function Cat(color) {
    this.color = color
    this.shangShu = function() {
      console.log('猫咪可以爬树')
    }
  }

  // 继承的核心代码:
  Cat.prototype = new Animal('jack', 18)

  // 设置被覆盖的constructor属性
  Cat.prototype.constructor = Cat

  const cat1 = new Cat('red', '111')
  const cat2 = new Cat('white', '222')
  console.log(cat1) // {color: "red", shangShu: ƒ}
  console.log(cat1.name) // jack 原型上的name
  console.log(cat1.age) // 18 原型链上的age
  console.log(cat1.color) // red 该对象的属性color
  cat1.shangShu() // 猫咪可以爬树
  cat1.eat() // 品味美食
  cat1.other.age = 2
  console.log('cat1.other.age', cat1.other.age); // cat1.other.age 2
  console.log('cat2.other.age', cat2.other.age); // cat2.other.age 2
console.log(cat1)

 借用继承

优点:1. 可以向父类构造函数传参;

           2. 不共享父类构造函数的引用属性

缺点:1. 方法不能复用,每个实例对象中继承来的方法是独立的,不是复用的

           2. 不能继承父类原型上的方法

  // - 设置需要被继承的构造函数Animal
  function Animal(name, age) {
    this.name = name
    this.age = age
    this.other = {
      age: 1
    }
    this.eat = function() {
      console.log('品味美食')
    }
  }

  Animal.prototype.say = function () {
    console.log('hello');
  }

  // - 再设置一个猫咪构造函数
  // 已经存在的构造函数Animal中具有了一些属性和方法,这些属性与方法是Cat构造函数需要的没有必要再书写一遍了,可以使用继承的方式获取
  function Cat(name, age) {
    // 通过call的方式,修改Animal中的this指向为当前Cat的this,并设置参数
    Animal.call(this, name, age)
  }

  const cat1 = new Cat('jack', 18)
  const cat2 = new Cat('张三', 22)
  console.log(cat1) // {name: "jack", age: 18, eat: ƒ}
  cat1.eat() // 品味美食
  try {
    cat1.say()
  } catch (e) {
    console.log(e.message); // cat1.say is not a function
  }
  cat1.other.age = 2
  console.log('cat1.other.age', cat1.other.age); // cat1.other.age 2
  console.log('cat2.other.age', cat2.other.age); // cat2.other.age 1

 

组合继承

优点:

1. 可以向父类构造函数传参

2. 可以复用父类原型上的方法

3. 不共享父类的引用属性

使用前面两种继承方式时发现各有优缺点,所以将两种方式结合即可
这种结合使用的方式称为组合继承,组合继承是最常用的一种继承方式。
  function Animal(name, age) {
    this.name = name
    this.age = age
    this.eat = function() {
      console.log('品味美食')
    }
  }

  function Cat(name, age, color) {
    // 使用借用构造函数的方式继承:
    Animal.call(this, name, age)
    this.color = color
    this.shangShu = function() {
      console.log('猫咪可以爬树')
    }
  }

  // 原型继承的核心代码:
  // 使用组合继承方式后,在构造函数体中就设置了实例属性,此处不需要传参
  // Cat.prototype = new Animal() // 不使用这种方式,因为会重复调用父类构造函数导致会存在多余的父类属性,使用下面的方式
  // Cat.prototype = Animal.prototype // 此方式当修复子类构造函数的执行后,父类实例的构造函数指向也会跟着变化
  // 通过创建中间对象,子类原型和父类原型就会隔离开,不是同一个。可以有效避免上面的的问题
  Cat.prototype = Object.create(Animal.prototype)

  // 设置被覆盖的constructor属性
  Cat.prototype.constructor = Cat

  const cat = new Cat('rose', 20, 'red')
  console.log(cat) // {name: "rose", age: 20, color: "red", eat: ƒ, shangShu: ƒ}
  console.log(cat.name) // rose
  console.log(cat.age) // 20
  console.log(cat.color) // red
  cat.shangShu() // 猫咪可以爬树
  cat.eat() // 品味美食
  console.log(cat.constructor)
  /**
   ƒ Cat(name, age, color) {
    // 使用借用构造函数的方式继承:
    Animal.call(this, name, age)
    this.color = color
    this.shangShu = function() {
      console.log('猫咪可以爬树')
    }
  }
   */

拷贝继承

使用继承的原型中的方法时,查找的次数会降低
  function Animal(name, age) {
    this.name = name
    this.age = age
    this.eat = function() {
      console.log('品味美食')
    }
  }

  function Cat(name, age, color) {
    // 使用借用构造函数的方式继承:
    Animal.call(this, name, age)
    this.color = color
    this.shangShu = function() {
      console.log('猫咪可以爬树')
    }
  }

  // 拷贝
  for (const k in Animal.prototype) {
    if (Animal.prototype.hasOwnProperty(k)) {
      Cat.prototype[k] = Animal.prototype[k]
    }
  }

  Cat.prototype.constructor = Cat

  const cat = new Cat('rose', 20, 'red')
  console.log(cat) // {name: "rose", age: 20, color: "red", eat: ƒ, shangShu: ƒ}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

__畫戟__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值