【问题标题】:How to extend an object literal class with Ecmascript 6 classes如何使用 Ecmascript 6 类扩展对象文字类
【发布时间】:2016-09-14 13:20:23
【问题描述】:

我有一个基础class 定义为object literal,其方法定义在构造函数的范围内。像这样:

var NodeMappingAbstract = function NodeMappingAbstract() {

    this.mapToContent = function (obj) {
        throw new Error('Not implemented');
    };

    this.getInfo = function (data) {
        throw new Error('Not implemented');
    };

    this.normalizeUri = function normalizeUri(uri) {
        return uriNormalizer.normalize(uri);
    };
};

如何使用 ES6 class 语法扩展NodeMappingAbstract?我尝试使用extendssuper()

class SomeMapping  extends  NodeMappingAbstract{
    constructor(){
        super();
    }

    mapToContent(rawElement) {
        console.warn('mapContent called');
        return rawElement;
    }
}

但是当我实例化它并像这样调用mapToContent 时:

let m = new SomeMapping();
m.mapToContent();

我得到Error: Not implemented,这意味着使用了NodeMappingAbstract 的实现。

【问题讨论】:

  • 我在你的代码中没有看到任何对象字面量?
  • @Bergi object literal 我的意思是NodeMappingAbstract 定义方法(作为实例属性)的方式。有没有更好的方法来调用这种模式?
  • 它被称为“具有特权方法的构造函数”。或者只是“特定于实例的方法”(它们的创建位置并不重要)。
  • @Bergi 谢谢!我必须学习很多关于 javascript 词汇表的知识:)

标签: javascript node.js ecmascript-6 nodes javascript-objects


【解决方案1】:

这里的问题是您将方法直接附加到NodeMappingAbstract (this) 的实例上,而不是函数的prototype

当 JavaScript 查找对象属性时,它首先检查对象直接拥有的属性,当您将某些内容分配给 this 时,这些属性是可用的。只有当它没有发现以这种方式立即可用的属性时,它才会转向prototype。因此,尽管您正在扩展 NodeMappingAbstract 并在 prototype 上定义方法(通过 class 糖),但您实际上并没有覆盖在 NodeMappingAbstract 内部实例化时分配给 this 的属性。

因此,将方法声明移出函数体并移到其prototype

var NodeMappingAbstract = function NodeMappingAbstract () {};

NodeMappingAbstract.prototype.mapToContent = function (obj) {
   throw new Error('Not implemented');
};

NodeMappingAbstract.prototype.getInfo = function (data) {
    throw new Error('Not implemented');
};

NodeMappingAbstract.prototype.normalizeUri = function normalizeUri (uri) {
    return uriNormalizer.normalize(uri);
};

【讨论】:

  • 这里是否可枚举并不重要 :-)
  • @Bergi 啊!谢谢!
  • 感谢您的解释!我想我无法重构NodeMappingAbstract,我在一个更大的代码库中工作,被奇怪的模式污染了
  • @JanOsch 那么你应该看看Bergi的答案并在构造函数中覆盖this上的方法:-)
【解决方案2】:

你应该把你的方法放在你的 ES5 类的原型上(你总是应该这样做的)。

如果您在构造函数中定义它们,并将它们创建为实例属性(它会影响从原型继承的任何内容),则在覆盖它们时您将不得不这样做:

class SomeMapping  extends  NodeMappingAbstract{
    constructor(){
        super();
        this.mapToContent = function(rawElement) {
            console.warn('mapContent called');
            return rawElement;
        };
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-24
    • 1970-01-01
    • 2015-09-15
    • 2017-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多