如果类明确扩展对象,为什么不可能调用方法



当我在打字稿中有一个明确扩展对象的类中的类,然后尝试调用该类的对象方法失败:

class Example extends Object {
    constructor() {
        super();
    }
    public getHello() : string {
        return "Hello";
    }
}
let greeter = new Example();
alert(greeter.getHello());

错误:greeter.getHello is not a function。这是为什么?如果我删除 extends-prause和 super()调用,则突然起作用。

我的问题是该代码是从自定义的JSWEET版本中自动化的,而我们仅移动代码库的某些部分。类层次结构中的类不应被映射到Object,因为extends在不重新更改JSWEET的情况下无法轻易删除。

我认为您可以说这是打字稿中的错误。可能不是高品位的,但是...: - (

这是因为Object忽略了它的 this,并返回一个新的空白对象。打字稿编译该编码的方式(针对ES5环境时(,它最终在Example中像这样调用Object

function Example() {
    return Object.call(this) || this;
}

Object.call(this)的结果是一个新对象,好像您做了{}

所以解决方案是...不要那样做。: - (

我的问题是该代码是从自定义的JSWEET版本中自动化的,而我们仅移动代码库的某些部分。类层次结构中的类不应被转移到对象,因为如果不大量更改JSWEET,则无法轻易删除扩展。

ouch。如果您可以定位ES2015 ,则问题消失了,因为这仅与版本TypeScript为ES5及更早创建。如果您不能,恐怕您听起来您想在"打字稿"问题列表上提交问题,并可能使用修复程序进行拉动请求。(我去寻找现有报告,但没有找到。(这与扩展其他内置INS(ErrorArray(略有不同,因为有一个非常简单的解决方案:只需忽略extends条款。

或,正如您在评论中提到的那样,您可以拥有一个没有做任何事情的虚拟课程,例如:

class FauxObject { }

然后使用它代替Object(class Example extends FauxObject(。


仅出于细节的缘故,完整的编译版本就是这样,Object的调用由******标记:

var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var Example = /** @class */ (function (_super) {
    __extends(Example, _super);
    function Example() {
        return _super.call(this) || this;             // ******
    }
    Example.prototype.getHello = function () {
        return "Hello";
    };
    return Example;
}(Object));
var greeter = new Example();
alert(greeter.getHello());

_super在您的情况下是Object

提交错误报告后,我被暗示到了一个FAQ条目,该输入涉及扩展Typescript的内置INS:

在ES2015中,返回对象的构造函数隐式将其值替换为Super(...(的任何呼叫者。生成的构造函数代码必须捕获超级(...(的任何潜在返回值并用此替换。

结果,子分类错误,数组和其他人可能不再按预期工作。这是由于以下事实:构造函数在错误,阵列和类似的功能上使用ecmascript 6的new.target来调整原型链。但是,没有办法确保新值的值。在Ecmascript 5中调用构造函数时。

解释类似于T.J.Crowder的答案,加上他们建议另一个其他解决方法:

作为建议,您可以在任何超级(...(调用后立即手动调整原型。

在我的情况下,将 Object.setPrototypeOf(this, Example.prototype);添加到构造函数中(或说服jsweet这样做(。

但是

不幸的是,这些解决方法将无法在 Internet Explorer 10 上使用。一个人可以手动从原型将方法复制到实例本身(即fooerror.prototype(,但是原型链本身无法修复。

编辑:我最终使用了此解决方法,因为我发现在我们的JSWEET项目中更容易实现。

编辑2:此解决方法还有其他缺点,因此我们继续使用了一个虚拟班,如接受的答案所述。