JavaScript——实现继承的几种方式

实现继承的6中方法:

  • 借用构造函数
  • 组合继承
  • 原型式继承
  • 寄生式继承
  • 寄生组合式继承
  • 拷贝继承

1. 借用构造函数

在子类型构造函数的内部调用超类构造函数。通过使用apply()和call()方法在新创建的对象上执行构造函数

可以在子类型构造函数中向超类型构造函数传递参数

缺点:只能继承超类型的实例属性,对于原型上的方法和属性无法继承。

function SuperType(name) {
  this.name = name;
  this.colors = ['red','blue','green']
}

function SubType() {
  // 继承SuperType
  SuperType.call(this,'ronghui');
  this.age = 19;
}

var instance1 = new SubType();
instance1.colors.push('black');
console.log(instance1.colors) // ["red", "blue", "green", "black"]
console.log(instance.name) // ronghui
console.log(instance.age) // 19

2. 组合继承

组合继承也叫伪经典继承,指的是将原型链和急用构造函数的技术组合到一块,从而发挥二者之长的一种继承模式。其背后的思路是使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的的继承。这样,既通过原型上定义方法实现了函数复用,又能够保证每个实例都有它自己的属性。

缺点:

  • 无论在什么情况下,都会调用两次超类型构造函数
  • 一次是在创建子类型原型的时候,另一次是在子类型构造函数内部,子类型会继承超类型对象的全部实例属性;
  • 这些实例属性可能不是我们想要的,因为我们还需要定义自己私有的属性,
  function SuperType(name) {
    this.name = name;
    this.colors = ['red', 'blue', 'green'];
  }

  SuperType.prototype.sayName = function () { console.log(this.name) }

  function SubType(name, age) {
    // 继承属性
    SuperType.call(this, name);
    this.age = age;
  }
  // 继承方法
  SubType.prototype = new SuperType();
  SubType.prototype.constructor = SubType;
  SubType.prototype.sayAge = function () { console.log(this.age) }

  var instance1 = new SubType('张三', 29);
  instance1.colors.push('block')
  console.log(instance1.colors) // ["red", "blue", "green", "block"]
  instance1.sayName() // 张三
  instance1.sayAge() // 29

  var instance2 = new SubType('李四', 24);
  console.log(instance2.colors); // ["red", "blue", "green"]
  instance2.sayName() // 李四
  instance2.sayAge() // 24

3. 原型式继承

function object(o) {
  function F()
  F.prototype = o;
  return new F()
}
var person = {
  name: '张三',
  f
}

ES5的Object.create()实现原型式继承,接受两个参数:一个用做新对象原型的对象和一个为新对象定义额外属性的对象。

 var person = {
      name: 'Nicholas',
      friends: ['Shelby', 'Court', 'Van']
    }

    var anotherPerson = Object.create(person);
    anotherPerson.name = 'Greg';
    anotherPerson.friends.push('Rob');

    var yetAnotherPerson = Object.create(person);
    yetAnotherPerson.name = 'Linda';
    yetAnotherPerson.friends.push('Barbie');
    console.log(person.friends); // ["Shelby", "Court", "Van", "Rob", "Barbie"]

4. 寄生式继承

function createAnother(original) {
  let clone = Object.create(original);
  clone.sayHi = function() { console.log( 'hi')}
  return clone
}

5. 寄生组合式继承

组合继承缺点:无论在什么情况下,都会调用两次超类型构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数颞部。

寄生组合继承,是通过借用构造函数来继承属性,通过原型链的混成形式来继承方法

function inheritPrototype(subType, superType) {
  var prototype = Object.create(superType.prototype);
  prototype.constructor = subType;
  subType.prototype = prototype;;
  
}
function SuperType(name) {
  this.name = name;
  this.colors = ['red', 'blue', 'green']
  
}
SuperType.prototype.sayName = function () {
  console.log(this.name)
}
function SubType(name, age) {
  SuperType.call(this, name);
  this.age = age;
}
inheritPrototype(SubType, SuperType);
SubType.prototype.sayAge = function () {
  console.log(this.age)
}
var instance1 = new SubType('张三', 18)
instance1.sayName() // 张三
instance1.sayAge(); // 18

6. 拷贝继承

for...in遍历原型

function Animal() { }
Animal.prototype.species = '动物';

function extends2(SubType, SupType) {
  var p = SupType.prototype;
  var c = SubType.prototype;
  for (var i in p) {
    c[i] = p[i]
  }
  
}

extends2(Cat, Animal);
var cat1 = new Cat('大毛', '黄色')
console.log(cat1.species)

posted @ 2019-10-28 21:26  dobeco  阅读(669)  评论(0编辑  收藏  举报