0%

es6class的一些迷惑点

今天在看 ts 的装饰器文档的时候,对于类装饰器的一节的官方示例感到非常迷惑

类装饰器接受一个参数,为类的 constructor,你可以观察,修改或者替换它。如果类装饰器返回了一个值,他会用提供的类的构造函数替换类的声明

1
2
3
4
5
6
7
8
function classDecorator<T extends { new (...args: any[]): {} }>(
constructor: T
) {
return class extends constructor {
newProperty = "new property";
hello = "override";
};
}

最让我迷惑的是 return class extends constructor,为什么可以继承构造函数?要求的返回值是构造函数,但是这里返回的是一个类的声明?

说到底还是自己对于 es6 的 class 理解不够透彻。我又去看了一下阮一峰的 es6 入门的 class 章节,上面说明 ES6 的 class 只是 es5 对象原型写法的语法糖。

1
2
3
4
5
6
class Point {
// ...
}

typeof Point; // "function"
Point === Point.prototype.constructor; // true

看到这里,感觉到就豁然开朗了。类名变量实际上就是类的构造函数,extends 类名变量 和 extends 构造函数的写法实质上是等价。

es6 类声明语法的返回值也是类的构造函数,所以返回匿名类的语法也可以理解了。

同时因为继承的是构造函数,所以 extends 的可以是一个构造函数

1
2
3
4
5
function A() {}
A.prototype.test = 1;
class B extends A {}
console.log(new B().test);
// 输出1

需要注意的一点是,要获取类的构造函数,应该使用 类名.prototype.constructor,我一直以为是 类名.constructor。类名变量是构造函数,实际上构造函数的 constructor 是函数原型对象的 constructor。