继承

139 阅读2分钟

首先 这是一个父类

// 父类
function Animal(name){
    this.name = name
    this.eat = function() {
        console.log(`${this.name} is eating`)
    }
}
Animal.prototype = {
    constructor: Animal,
    sayName() {
        console.log(`my name is ${this.name}`);
    }
}

继承的方式有以下几种,下面我们详细介绍这几种继承方式

  1. 构造函数继承
  2. 原型链继承
  3. 组合继承
  4. 原型式继承
  5. 寄生式继承
  6. 寄生组合式继承

1. 构造函数继承

构造函数(只能继承属性,不能继承原型prototype上的方法, Cat上没有sayName的方法)

function Cat(name, age) {
   Animal.call(this, name) 
   this.age = age
}
Cat.prototype = {
    sheep() {
        console.log(`${this.name} is sheeping`);
    }
}
var cat = new Cat('cat', 12)
console.log(Cat.prototype.constructor === Cat) // false
console.log(cat instanceof Animal); // false 
console.log(cat instanceof Cat); // true

// 总结:
// 1. 实例只是子类Cat的不是父类Animal的实例 
// 2. 子类Cat不能继承父类Animal的prototype上的属性
// 3. 子类Cat可以继承多个父类
// 4. 继承多个父类的所有属性

2. 原型链继承

function Cat() {}
Cat.prototype = new Animal('cat')
console.log(Cat.prototype.constructor === Cat) // false, 所以上面应该重新赋值
console.log(a instanceof Animal) // true
console.log(a instanceof Cat) // true

总结

  1. 实例是子类Cat也是父类Animal的实例
  2. 构造器Cat是完全继承的Animal,没有自己的属性和方法
  3. 构造的实例无法向构造器传参
  4. 让Cat原型等于父类的实例。

3. 实例继承

function Cat(name, age) {
    var instance = new Animal(name)
    instance.age = age
    return instance;
}
Cat.prototype = {
    constructor: Animal,
    sheep() {
        console.log(`${this.name} is sheeping`);
    }
}
var cat = new Cat('cat', 12)
console.log(Cat.prototype.constructor === Cat) // true
console.log(cat instanceof Animal); // true 
console.log(cat instanceof Cat); // false

总结

  1. 实例只是父类的实例不是子类的实例
  2. 可以添加属性和方法

4. 拷贝继承

function Cat(name, age) {
    var instance = new Animal(name)
    for(let o in instance) {
        Cat.prototype[o] = instance[o]
    }
    Cat.prototype.name = name
    Cat.prototype.age = age
}
console.log(a instanceof Cat) // false
console.log(a instanceof Animal) // true

总结

  1. 实例只是父类的实例不是子类的实例
  2. 可以添加属性和方法
  3. 无法拷贝不可枚举的属性
  4. for循环效率低

5. 对象冒充

6. 组合继承

function Cat(name, age){
  Animal.call(this, name);
  this.age = age
}
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat; // 需要修改
console.log(a instanceof Cat) // true
console.log(a instanceof Animal) // false

7. 寄生组合继承

function Cat(name, age){
  Animal.call(this, name);
  this.age = age
}

// 创建一个没有实例方法的类
var Super = function(){};
Super.prototype = Animal.prototype;
//将实例作为子类的原型
Cat.prototype = new Super();
Cat.prototype.constructor = Cat; // 需要修复下构造函数
console.log(a instanceof Cat) // true
console.log(a instanceof Animal) // true

function content(obj) {
    function F() {}
    F.prototype = obj
    return new F()
}
const sup = new Animal()
function subobject(obj) {
    var sub = content(obj)
    sub.name = 'gar'
    return sub
}
const sup2 = subobject(sup)
console.log(sup2)
sup2.eat()
sup2.sayName()

8.原型式继承

function content2(obj) {
    function F() {}
    F.prototype = obj
    return new F()
}
const sup3 = new Animal()
const sup4 = content2(sup3)
console.log(sup4.name, 1, sup4 instanceof Animal)
sup4.eat()
sup4.sayName()

9.构造函数继承+寄生继承

function Pig(name) {
    Animal.call(this, name)
}
function content3(obj) {
    function F() {}
    F.prototype = obj;
    return new F()
}
const sup6 = content3(Animal.prototype)
Pig.prototype = sup6;
sup6.constructor = Pig;
const sup5 = new Pig('111')
console.log(sup5)
sup5.eat()
sup5.sayName()