先来一个父类

function Animal(name) {
    this.name = name || ''
    this.sleep = function () {
        console.log('sleep');
    }
}

原型链继承

function Dog() {

}
Dog.prototype = new Animal() //在这里继承了Animal的实例方法和原型方法,但是constructor也变成了Animal.prototype.constructor即Animal所以下面应该修改回来
Dog.prototype.constructor = Dog
let dog = new Dog()
dog.sleep()
dog.eat()

构造继承

function Dog(){
    Animal.call(this) //只能继承实例属性与实例方法,无法继承原型上的属性与方法。可以多继承
}
let dog = new Dog()

实例继承

function Dog(name){
    let instance = new Animal()
    instance.name = name ||'dog'
    return instance
}

组合继承

function Dog(){
    Animal.call(this)
}
Dog.prototype = new Animal()
Dog.prototype.constructor = Dog

拷贝继承

function Dog(){
    let animal = new Animal()
    for(var p in animal){
        Dog.prototype[p] = animal[p]
    }
}

寄生组合继承

function Dog(){
    Animal.call(this)
}
(function(){
    var Super = function(){}
    Super.prototype = Animal.prototype
    Dog.prototype = new Super()
})()
Dog.prototype.constructor = Dog

ES6

class Animal{
    constructor(){
        this.name = name
    }
}
class Dog extends Animal{
    constructor(args){
        super(args)
    }
}

ES6继承与ES5的区别

  • class 声明会提升,但不会初始化赋值。Foo 进入暂时性死区,类似于 let、const 声明变量。
  • class 声明内部会启用严格模式。
  • class 的所有方法(包括静态方法和实例方法)都是不可枚举的。
  • class 的所有方法(包括静态方法和实例方法)都没有原型对象 prototype,所以也没有[[construct]],不能使用 new 来调用
  • 必须使用 new 调用 class。
  • class 内部无法重写类名。