TypeScript 建议:为更好的ES5/ES6类互操作性添加新的__construct辅助函数 翻译结果:建议:为更好的ES5/ES6类互操作性添加新的构造函数辅助函数

nuypyhwy  于 4个月前  发布在  TypeScript
关注(0)|答案(3)|浏览(139)

我建议我们在使用--target ES5编译时,为扩展ES6内置类的类示例构造运行时语义添加一个新的辅助函数。

背景

我们当前为--target ES5生成的类假设其超类遵循与我们生成的类相同的运行时语义。通常这意味着可以通过call()apply()将构造函数作为函数调用。然而,一些ES6内置类在未用作构造函数时被指定为抛出异常(即PromiseMap等),而其他ES6内置类在调用时返回值,忽略提供给call()apply()this值(即ErrorArray等)。
以前我们为支持后一种情况提供了可能的解决方法,但目前我们还没有解决方案来解决前一种情况。

建议

以下代码清单描述了我们需要为包含显式(或隐式,用于属性声明)的super()调用的任何文件发出的新__construct辅助函数:

class MyPromise extends Promise {
  constructor(executor) {
    super(executor);
  }
}

// becomes...
var __extends = ...;
var __construct = (this && this.__construct) || (typeof Reflect !== "undefined" && Reflect.construct
    ? function (s, t, a, n) { return t !== null ? Reflect.construct(t, a, n) : s; }
    : function (s, t, a) { return t !== null && t.apply(s, a) || s; });

var MyPromise = (function (_super) {
  __extends(MyPromise, _super);
  function MyPromise(executor) {
    var _this = this;
    var _newTarget = this.constructor;
    _this = __construct(this, _super, [executor], _newTarget);
    return _this;
  }
  return MyPromise;
})(Promise);

好处

  • 通过特性检测Reflect.construct,允许下级类发射扩展ES6内置类(如果在ES6宿主中运行)。
  • 在ES5宿主中运行时回退到现有行为。
  • x等于null时,以与现有行为相同的方式处理extends nullextends x
  • 以与现有行为相同的方式处理来自super的自定义返回值。

缺点

  • 更大的辅助函数占用空间
  • 在ES5宿主中对内置类进行子类化与在ES6宿主中对内置类进行子类化具有不同的运行时语义:
  • 在ES5中,对ArrayError进行子类化将不具有正确的原型链。唯一的解决方案是根据已建立的指导方针,使用非标准属性__proto__显式设置原型链。
u0sqgete

u0sqgete1#

尽管这将增加更多的辅助开销,但我们可以通过$x_{1m0n1}^{x}$来考虑一种最佳努力的方法来解决子类化缺点:

$x_{1a0b1}^{x}$

qco9c6ql

qco9c6ql2#

尝试使用原生WebComponents与Typescript目前并不十分符合人体工程学,因为首先我们需要针对es2015(或更高目标),然后使用支持此功能的babel
我知道添加大量特定设置可能需要避免,但是否可以最小化更改,使其具有一个标志(例如useClassReflectConstruct),始终输出Reflect.construct(...)而不是.apply(...)?
在es5浏览器中简单地包含一个polyfill for Reflect.construct,并在tsconfig.json中设置此选项以支持使用Web组件和扩展原生对象而无需麻烦。
对于同一功能还有三个其他问题待解决。是什么阻碍了这一进展?它可以作为PR添加吗?

zd287kbt

zd287kbt3#

使用Reflect.construct编译的问题是,this.constructor属性不能被覆盖或以其他方式阻碍;但这与支持编译new.target所需的警告相同。

相关问题