1.组合继承

function Parent(name) {
    this.name = name;
}
Parent.prototype.getValue = function() {
  console.log(this.val)
}
function Son(name) {
    Parent.call(this, name); //继承属性
    this.A = function a(){}
}

Son.prototype = new Parent(); //继承方法

缺点就是在继承父类函数的时候调用了父类构造函数,导致子类的原型上多了不需要的父类属性,存在内存上的浪费。创建实例时,相当于调用了两次父类的构造函数,使得实例属性和原型链上属性重复。

2.寄生组合继承

function Parent(name) {
    this.name = name;
}
Parent.prototype.getValue = function() {
  console.log(this.val)
}
function Son(name) {
    Parent.call(this, name); //继承属性
}

Son.prototype = Object.create(Parent.prototype); //继承方法
Son.prototype.constructor = Son; //把构造函数指向子类构造函数。

3.class继承

class Son extends Parent {
   constructor(name) {
       super(name);
   }
   A() {
   }
}

call apply bind
都是为了解决this指向的问题。
call和apply传入的参数不同
getValue.call(a, 'yck', '24')
getValue.apply(a, ['yck', '24'])
call和apply是立即执行,bind是返回一个this固定的函数。

手写bind

Function.prototype.bind1 = function() {
    const args = Array.prototype.slice.apply(arguments)
    const t = args.shift()
    const self = this
    return function() {
        return self.apply(t, args)
    }
}

手写apply

Function.prototype.apply1 = function() {
    let context = argments[0]
    context.fn = this
    let result;
    if(arguments[1]) {
        result = context.fn(...argments[1])
    }
    else {
        result = context.fn()
    }
    delete context.fn
    return result;
}