Jan Grz
Jan Grz

Reputation: 1471

How to extend an object literal class with Ecmascript 6 classes

I have a base class defined as an object literal, with methods defined inside constructor's scope. Like this:

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);
    };
};

How do I extend theNodeMappingAbstract with ES6 class syntax? I attempted using extends and super():

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

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

But when I instantiate it and call mapToContent like this:

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

I get Error: Not implemented, which means the implementation of the NodeMappingAbstract is used.

Upvotes: 2

Views: 681

Answers (2)

sdgluck
sdgluck

Reputation: 27247

The problem here is that you are attaching the methods directly on an instance of NodeMappingAbstract (this), and not the prototype of the function.

When JavaScript performs a lookup for an object property it first inspects the objects immediate own properties, which are what are made available when you assign something to this. Only if it does not find that property immediately available in this way will it turn to the prototype. So, although you are extending the NodeMappingAbstract and defining methods on the prototype (via the class sugar), you are not actually overriding the properties that are assigned to this on instantiation inside NodeMappingAbstract.

So, move the method declarations outside of the function body and onto its 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);
};

Upvotes: 5

Bergi
Bergi

Reputation: 664579

You should put your methods on the prototype of your ES5 class (as you always should).

If you define them in the constructor, and create them as instance properties (which shadow anything inherited from the prototype), you will have to do the same when overwriting them:

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

Upvotes: 2

Related Questions