【问题标题】:Cannot assign to read only property: Typescript + Babel无法分配给只读属性:Typescript + Babel
【发布时间】:2016-01-06 22:35:57
【问题描述】:

我编译的打字稿在运行时遇到问题。我的链是 Typescript -> es6 模块 -> webpack + babelify。

有问题的文件是

import Registry from "../registry";

class Alert {

    public static name = "alert";

    public static options = {
        template: require("./alert.mustache")
    };
}

Registry.register(Alert);

这是通过 es2015 插件 + webpack 编译到

"use strict";

var _registry = __webpack_require__(14);

var _registry2 = _interopRequireDefault(_registry);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var Alert = function Alert() {
    _classCallCheck(this, Alert);
};

Alert.name = "alert";
Alert.options = {
    template: __webpack_require__(16)
};
_registry2.default.register(Alert);
//# sourceMappingURL=alert.js.map

/*****************
 ** WEBPACK FOOTER
 ** alert.js
 ** module id = 15
 ** module chunks = 0
 **/

但是在执行时,得到这个错误:

alert.js:15 Uncaught TypeError: Cannot assign to read only property 'name' of function Alert() {
    _classCallCheck(this, Alert);
}

我尝试了很多不同的方法,但我不明白为什么在类上使用静态属性会导致这个问题。

提前致谢。

【问题讨论】:

  • 这是一个打字稿编译器问题:在 ES2015 中,name 函数属性是只读的。所以 TS 编译器必须考虑到这一点。
  • 哇,非常感谢。你帮我省了很多麻烦。
  • 如果您提交错误,请提供链接吗?

标签: typescript webpack babeljs


【解决方案1】:

name 属性是描述函数名称的reserved property on functions,即用于function foo()foo.name === 'foo'。它在 EcmaScript 规范中定义为只读属性。因此,您的转译代码最终会尝试分配给您的 Alert 函数的 name 属性,该属性是只读的,并且失败:

var Alert = function Alert() {
    _classCallCheck(this, Alert);
};

// This is not allowed, because
// [[Function]].name is a read-only property.
Alert.name = "alert";

【讨论】:

  • "it is transpiled down to" --- 如果编译器使用Map 来保留静态成员,那将不是问题。
  • 对不起,我不明白你的评论。为什么假设编译器可以做些什么来避免名称冲突很重要?编译器也可以混淆运行时属性的名称以避免冲突。那么你能解释一下你的意思吗?
  • 这是对您答案的补充:编译器不必将 TS 中的标识符名称直接 1:1 转换为 JS 中的标识符。并且要强调的是,通常是编译器负责修改名称,而不是用户的问题来考虑底层运行时的某些限制(您甚至无法直接访问)。
【解决方案2】:

代码:

class Alert {

    public static name = "alert";

在运行时无效。您不能编写 functionname 属性(如果您转译为 es5,这就是类)。使用instanceof 运算符进行类实例检查。

There is an open issue on github to turn this into a compiler error.

【讨论】:

  • "在运行时无效" --- 这到底是什么意思?按照 TS 语言标准是无效的吗?
  • 不符合 JavaScript 标准。见developer.mozilla.org/en/docs/Web/JavaScript/Reference/…Writable : no
  • 这是不正确的:高级语言必须解决低级语言的细微差别。仅仅因为编译器有错误就说它是“无效的”是错误的。
  • 编译器有错误。它在运行时无效。我没有看到我们不同意
  • “代码在运行时无效”---根本上是错误的。如果只有语言标准/规范这么说,代码可能在语法上是错误的,或者它的运行时语义可能是错误的。 TS 规范是否禁止用户使用名称为name 的静态成员? “你不能写函数的名称属性”---代码没有修改函数的name属性。该代码定义了一个类的静态成员。
猜你喜欢
  • 1970-01-01
  • 2019-05-08
  • 2017-11-30
  • 2019-12-06
  • 2020-02-17
  • 2014-12-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多