关于ES5和ES6的继承问题(区别吧)

ES5的继承方式主要是组合继承,即构造函数继承(apply、call改变this的指向,立即执行获得父类的方法和属性)+原型链继承(父类的实例构成子类的原型对象)。

function Parent(name) {
  this.name = name;
  this.say = function () {
    console.log('父的say');
  }
}
Parent.prototype.age = 8;
Parent.prototype.sleep = function () {
  console.log('父的sleep');
}

function Chlid(name) {
  this.li = '子的li'
  Parent.call(this, name);
  //构造函数继承,先创建子类实例对象this,在将父类的方法和属性添加到this上面。
}
//原型链继承,总的说就是子类的原型对象指向父类的原型对象(内存地址相同,要想不同就深克隆再赋值)
function fn() {}
fn.prototype = Parent.prototype;
Chlid.prototype = new fn();
//对象增强,修复缺失的constructor。
Chlid.prototype.constructor = Chlid;

var p = new Chlid('小明');
console.log(p);
//Chlid { li: '子的li', name: '小明', say: [Function] }
console.log(p.age);
//8
p.sleep()
//父的sleep

ES6的继承则用语法糖class和extends。构造函数放到constructor的函数中,其余的方法放在constructor函数外,这些函数相当于Chlid.prototype中的设置。

class Parent {
//这里就是prototype的constructor(相当于)
  constructor(name) {
    this.name = name;
    this.say = function () {
      console.log('父的say');
    }
  }
  age = 8;
  //相当于Parent.prototype.sleep()
  sleep() {
    console.log('父的sleep');
  }
}

class Chlid extends Parent {
  constructor(name) {
    super(name);
    this.li = '子的li'
  }
}

var p = new Chlid('小明');
console.log(p);
//Chlid { age: 8, name: '小明', say: [Function], li: '子的li' }
Chlid.prototype.sleep()
//父的sleep
console.log(Chlid.prototype.age);
//undefined,比较奇怪,不是在原型对象里面,也不是类的静态数据,只要实例能够访问到。
console.log(Chlid.age);
//undefined
console.log(p.age);
//8
p.sleep()
//父的sleep
//Chlid.sleep()则是错误的,不存在。

ES5 的继承,实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面(Parent.apply(this))。

ES6 的继承机制完全不同,实质是先将父类实例对象的属性和方法,加到this上面(所以必须先调用super方法),然后再用子类的构造函数修改this。

在子类的构造函数中,只有调用super之后,才可以使用this关键字,否则会报错。这是因为子类实例的构建,基于父类实例,只有super方法才能调用父类实例。

ES6类继承的本质:
class A extends B{}

  1. A.__proto__ === B; //继承父类静态属性或方法。
  2. A.prototype.__proto__ == B.prototype;//实例继承链。
  3. 子类的构造函数中必定调用父类的构造函数。
  4. super作为对象时,在普通方法中,指向父类的原型对象( 即 B.prototype );在静态方法中,指向父类( 即 B )。

参考博客链接:

你可能感兴趣的:(刷题系列)