关于此问题我还阅读了以下内容
贺师俊的回答:https://www.zhihu.com/question/391196995
刘家忍的文章:https://zhuanlan.zhihu.com/p/258906525
关于此问题我还阅读了以下内容
贺师俊的回答:https://www.zhihu.com/question/391196995
刘家忍的文章:https://zhuanlan.zhihu.com/p/258906525
2生成了_this.age2 = void 0也没什么问题啊,如果你想像3这样不生成,可以class TestClass2 extends TestClass1 {
declare age2?: number; 这样写
你可能没明白我的意思。
1)3.0之前不需要写,为什么3.0之后需要这样写。
2)这是官方的编译器修改后产生的代码,所以我想从知道官方这么做的原因,为什么要多生成这一句,不生成其实就跟tsc的效果一致了。
3) useDefineForClassFields本身是可配置,所以使用上无所谓,关闭了就是。但是目前多了这一句,导致跟预期的不符。
2.x是tsc编译的,3.x是babel编译的。这个可能是tsc和babel之间的差别的,但我也不是很懂他们之间具体有多少差异
那我去试一下babel编译的效果。看看跟tsc编译的差多少。
babel编译
var TestClass2 = /*#__PURE__*/function (_TestClass) {
_inherits(TestClass2, _TestClass);
var _super = _createSuper(TestClass2);
function TestClass2() {
_classCallCheck(this, TestClass2);
return _super.call(this);
}
_createClass(TestClass2, [{
key: "init",
value: function init() {
_get(_getPrototypeOf(TestClass2.prototype), "init", this).call(this);
this.age2 = 100;
console.log("age2:".concat(this.age2));
}
}]);
return TestClass2;
}(TestClass1);
也没看见有生成上面那一句
顶一下顶一下
3.x 内部使用 babel 编译代码。
Creator 选项 !useDefineForClassFields
对应 @babel/preset-env
、@babel/plugin-proposal-class-properties
的 loose
;
Creator 选项 allowDeclareFields
对应 @babel/preset-typescript
的 allowDeclareFields
。
我使用最新的 babel 测试了所有组合的情况,发现它们都会将 age2
初始化为 undefined
。以下是我的测试代码:
babel-test.zip (23.9 KB)
在 useDefineForClassFields
为false时不使用@babel/plugin-proposal-class-properties
const babel = require('@babel/core');
const fs = require('fs-extra');
const env = require('@babel/preset-env');
const ts = require('@babel/preset-typescript');
const classProperties = require('@babel/plugin-proposal-class-properties');
(async (input = './input.ts') => {
await transform('false-false.js', false, false);
async function transform(output, useDefineForClassFields, allowDeclareFields) {
const loose = !useDefineForClassFields;
let plugins = [];
//如果为false不使用plugin
if (useDefineForClassFields) {
plugins.push([classProperties, { loose }]);
}
const result = await babel.transformFileAsync(
input,
{
presets: [
[env, { loose }],
[ts, { allowDeclareFields }],
],
plugins: plugins,
}
);
await fs.writeFile(output, result.code);
}
})();
编译出来就不会有那一句
"use strict";
function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
var TestClass1 = /*#__PURE__*/function () {
function TestClass1() {
this.init();
}
var _proto = TestClass1.prototype;
_proto.init = function init() {
this.age1 = 10;
console.log("age1:" + this.age1);
};
return TestClass1;
}();
var TestClass2 = /*#__PURE__*/function (_TestClass) {
_inheritsLoose(TestClass2, _TestClass);
function TestClass2() {
return _TestClass.call(this) || this;
}
var _proto2 = TestClass2.prototype;
_proto2.init = function init() {
_TestClass.prototype.init.call(this);
this.age2 = 100;
console.log("age2:" + this.age2);
};
return TestClass2;
}(TestClass1);
其实诉求很简单,就是在不使用这个选项的时候,和之前行为一致就行。不需要再额外写一个declare。虽然简单且解决问题,但是麻烦。
loose 有没有设置为 “true”?
const loose = !useDefineForClassFields;
useDefineForClassFields为false, loose当然是true了.
一样会生成.
只要使用了这个插件 不管loose是true还是false,一定会生成
_this.age2 = void 0;
如下:
var TestClass2 = /*#__PURE__*/function (_TestClass) {
_inheritsLoose(TestClass2, _TestClass);
function TestClass2() {
var _this;
_this = _TestClass.call(this) || this;
_this.age2 = void 0; // 这边这个
return _this;
}
var _proto2 = TestClass2.prototype;
_proto2.init = function init() {
_TestClass.prototype.init.call(this);
this.age2 = 100;
console.log("age2:" + this.age2);
};
return TestClass2;
}(TestClass1);
但是如果在 useDefineForClassFields=false
的情况下,不使用这个插件. 则不会生成.
3.5 会修复这个问题。3.5 之后:
符合规范的类字段 | 允许声明类字段 | 未指定初始化式的字段 | 初始化语义 |
---|---|---|---|
是 | 是 | 使用 Define 语义初始化为 undefined
|
Define |
否 | 是 | 使用 Set 语义初始化为 undefined
|
Set |
是 | 否 | 不生成代码 | Define |
否 | 否 | 不生成代码 | Set |
其中:
初始化语义 Define
是指使用 Object.defineProperty()
定义、初始化类字段;
初始化语义 Set
是指使用 this./* 字段名 */ = /* 初始化式 */
初始化类字段;
不生成代码是指这段代码不起作用,相当于没写。
另外,只要字段上面使用了装饰器。都会用 Define
语义来初始化。
该主题在最后一个回复创建后14天后自动关闭。不再允许新的回复。