【图解】ES6Class类继承原理及其与ES5继承⽅式的区别
上⼀篇⽂章我们详细讨论了ES5的各种继承⽅式,及其优缺点。最终总结出⼀种最优的继承⽅式--寄⽣组合式继承。虽然它克服了其他继承⽅式的缺点,但代码⽐较复杂,功能也⽐较单⼀。⽽这篇所讨论的Class类继承是⼀种更好的继承⽅式,不过基本上,Class可以看作只是⼀个语法糖,它的绝⼤部分功能,ES5都可以做到。新的class写法,只是让于对象原型的写法更加清晰,更像⾯向对象编程的语法⽽已。(注:本⽂只探讨Class的原理,具体使⽤⽅法有很多相关资料可查阅)
1. 类的实现
ES6写法:
1 class Parent {
2  constructor(a){
3    this.filed1 = a;
4  }
5  filed2 = 2;
6  func1 = function(){}
7 }
Babel转换后:(可以看到其底层仍然是构造函数实现的)
function _classCallCheck(instance, Constructor) {
 // instanceof 检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
7 var Parent = function Parent(a) {
// (1) 调⽤_classCallCheck⽅法判断当前函数调⽤前是否有new关键字,构造函数执⾏前有new关键字,
      会在构造函数内部创建⼀个空对象,将这个空对象的__prpto__指向构造函数的原型,并将this指向这个空
      对象。如上,_classCallCheck中:this instanceof Parent,返回true.
_classCallCheck(this, Parent);
this.filed2 = 2;    // (2) 将class内部的变量函数赋值给this
this.func1 = function () { };
this.filed1 = a;    // (3) 执⾏constructor内部的逻辑
};
2. 继承的实现
ES6写法:
1 class Child extends Parent {
2    constructor(a,b) {
3      super(a);
4      this.filed3 = b;
5    }
6
7  filed4 = 1;
8  func2 = function(){}
9 }
Babel转化后:
"use strict";var Child = function (_Parent) {
_inherits(Child, _Parent);  // (1) 调⽤_inherits函数继承⽗类的prototype
// (2) ⽤⼀个闭包保存⽗类引⽤,在闭包内部做⼦类构造逻辑
function Child(a, b) {
_classCallCheck(this, Child);  // (3) 校验是否使⽤new调⽤
var _this = _possibleConstructorReturn(this, (Child.__proto__ || PrototypeOf(Child)).call(this, a));  // (4) ⽤当前this调⽤⽗类构造函数.    _this.filed4 = 1;  // (5) 执⾏⼦类class内部的变量和函数赋给this
_this.func2 = function () {};
_this.filed3 = b;  // (6) 执⾏⼦类constructor内部逻辑
return _this;
}
return Child;
}(Parent);
function _inherits(subClass, superClass) {
// (1) 校验⽗构造函数
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}
// (2) 利⽤寄⽣继承的⽅法继承⽗类原型
subClass.prototype = ate(superClass && superClass.prototype, {
constructor: { value: subClass, enumerable: false, writable: true, configurable: true }
});
// (3) 将⼦构造函数的_proto_指向⽗构造函数,这⾥的setPrototypeOF()⽅法与create()类似,
      到这步可以看出class继承同时存在两条继承链,⼦类构造函数的__proto__指向⽗类,⼦类原型的__proto__指向⽗类原型
if (superClass)
Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}
function _possibleConstructorReturn(self, call) {
// 校验this是否被初始化,super是否调⽤,并返回⽗类已经赋值完的this
if (!self) {
函数prototypethrow new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return call && (typeof call === "object" || typeof call === "function") ? call : self;
}
super
super代表⽗类构造函数, super.fun1() 等同于 Parent.fun1() 或 Parent.prototype.fun1()。super() 等同于strutor(). 默认的构造函数中会主动调⽤⽗类构造函数,并默认把当前constructor传递的参数传给了⽗类。所以当我们声明了constructor后必须主动调⽤super(),否则⽆法调⽤⽗构造函数,⽆法完成继承。
3. 总结
1.  class类内部定义的所有⽅法都是不可枚举的。这点和ES5⾏为不⼀致。
2. 类和模块的内部默认使⽤严格模式,所以不需要使⽤use strict指定运⾏模式。
3. 类必须使⽤ new 来调⽤,否则会报错。这是他跟普通构造函数的⼀个主要区别,后者不⽤ new 也可以执⾏。
4. 类内部不存在变量提升,这⼀点与ES5完全不同。
5. class继承可以实现原⽣构造函数的继承,⽽ES5不可以。