1. 派生类的 constructor 必须显式定义:跟 C#、Java 等语言会默认创建调用父类构造逻辑的 constructor 不一样,ES6 的 Class 要求派生类明确写上 constructor 并在其中调用 super 函数以确保父类构造逻辑运行
2. ES6 的 Class 在声明的时候,extends 的父类可以是运算结果,于是乎,相比起静态语言,可玩的东西很多,例如通过 Higer-Order Components 的模式来实现类似 mixin 的效果:
'use strict';
function helloSayable(Class) {
return class extends Class {
sayHello() {
console.log('hello');
}
}
}
class A extends helloSayable(React.Component) {
}
const a = new A;
a.sayHello(); // hello
3. ES 6 的 Class 上的 static 成员在其派生类上将被包含:
'use strict';
class A {
static methodOnA() {
console.log('methodOnA');
}
}
class B extends A {
}
class C extends A {
static methodOnA() {
console.log('methodOnA overrided by C');
}
}
B.methodOnA(); // prints: methodOnA
C.methodOnA(); // prints: methodOnA overrided by C
这点超越了以往简单地通过 DerivedClass.prototype = new BaseClass() 的方式来实现继承达成的效果,实际上也确实更符合大家关于继承行为的预期,那具体底层做了什么呢?把上述代码在 Babel 中跑一趟后,从编译得的代码可以看出端倪,请留意加粗那段:
'use strict';
function _inherits(subClass, superClass) {
if (typeof superClass !== 'function' && superClass !== null) {
throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass)
Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError('Cannot call a class as a function');
}
}
var A = function () {
function A() {
_classCallCheck(this, A);
}
A.methodOnA = function methodOnA() {
console.log('methodOnA');
};
return A;
}();
var B = function (_A) {
_inherits(B, _A);
function B() {
_classCallCheck(this, B);
_A.apply(this, arguments);
}
return B;
}(A);
var C = function (_A2) {
_inherits(C, _A2);
function C() {
_classCallCheck(this, C);
_A2.apply(this, arguments);
}
C.methodOnA = function methodOnA() {
console.log('methodOnA overrided by C');
};
return C;
}(A);
B.methodOnA();
C.methodOnA();
4. 跟 React.createClass 的情况不一样,ES6 的 Class 构造出来的对象上的方法默认不绑定到 this 上,所以传递时如果预期 this 不漂移,需要 bind(this) 一下再传,或者在 constructor 中对方法进行一遍替换,例如:
class A extends React.Component {
constructor() {
super(...arguments);
for (let i in this) {
const method = this[i];
if (method instanceof Function) {
this[i] = this[i].bind(this);
}
}
}
}