首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如果一个类明确地扩展了对象,为什么不能调用方法呢?

如果一个类明确地扩展了对象,为什么不能调用方法呢?
EN

Stack Overflow用户
提问于 2019-05-07 12:02:22
回答 2查看 246关注 0票数 5

当类型记录中有一个类可以明确扩展对象时,尝试调用该类的Object方法失败:

代码语言:javascript
复制
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-clause和super()调用,那么它就突然起作用了。

我的问题是,代码是从自定义的JSweet版本自动生成的,我们只转换了代码库的一部分。不应该转移的类层次结构中的类被简单地映射到Object,因为在不大量更改JSweet的情况下很难删除extends

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-05-07 12:11:09

我认为您可能会认为这是TypeScript中的一个bug。可能不是最重要的,但是.:-)

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

代码语言:javascript
复制
function Example() {
    return Object.call(this) || this;
}

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

所以解决办法是.别那么做。:-)

我的问题是,代码是从自定义的JSweet版本自动生成的,我们只转换了代码库的一部分。类层次结构中不应该被转移的类被简单地映射到对象,因为如果不大量地更改JSweet,扩展很难被移除。

唉哟。如果您可以针对ES2015+,问题就会消失,因为这只与TypeScript为ES5和更早版本创建的版本有关。如果你做不到,我恐怕你会想要在TypeScript问题清单上提交一个问题,或者用一个修复程序执行一个拉请求。(我去找了一份现有的报告,但没有找到。)这与扩展其他内置(ErrorArray)略有不同,因为有一个非常简单的解决方案:忽略extends子句。

或者,正如您在评论中提到的,您可以有一个虚拟类,它什么都不做,比如:

代码语言:javascript
复制
class FauxObject { }

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

为了详细起见,完整的编译版本是这样的,对Object的调用是用******标记的

代码语言:javascript
复制
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

票数 6
EN

Stack Overflow用户

发布于 2019-05-08 10:20:53

在提交了一个错误报告后,我被告知一个常见问题条目,用于扩展类型记录内置程序。

在ES2015中,返回对象的构造函数隐式地替代了超级(.)的任何调用者的值。生成的构造函数代码必须捕获超级(.)的任何潜在返回值。用这个代替它。 因此,子类错误、Array等可能不再按预期工作。这是因为构造函数函数用于错误、数组等,使用ECMAScript 6的new.target来调整原型链;但是,在调用ECMAScript 5中的构造函数时,无法确保new.target的值。默认情况下,其他底层编译器通常也有相同的限制。

这一解释类似于T.J.克劳德的回答,此外,他们还推荐了另一种解决办法:

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

在我的示例中,这将是将Object.setPrototypeOf(this, Example.prototype);添加到构造函数中(或说服JSweet这样做)。

不幸的是,这些解决方案不能在Internet 10和更高版本上使用。可以手动将方法从原型复制到实例本身(即FooError.prototype复制到此),但是prototype链本身无法修复。

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

编辑2:这个解决方法还有其他的缺点,所以我们继续使用了一个虚拟类,正如在接受的答案中所简要描述的那样。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56022190

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档