Adam
Adam

Reputation: 5233

ES6 use `super` out of class definition

I'm trying to add extra methods to class, and these extra methods should use the super methods.

If I add them in the model definition, it works.

class A {
    doSomething() {
        console.log('logSomething');
    }

}

class B extends A {
    doSomething() {
        super.doSomething();
        console.log('logSomethingElse');
    }
}

If I try to add the extra method to B.prototype, I'll get SyntaxError: 'super' keyword unexpected here.

class A {
    doSomething() {
        console.log('logSomething');
    }

}

class B extends A {
}

B.prototype.doSomething = function doSomething() {
    super.doSomething();
    console.log('logSomethingElse');
}

It is quite clear, why I get this error. This is a function and not a class method.

Let's try to define the method as a class method, and copy it to the original B class:

class A {
    doSomething() {
        console.log('logSomething');
    }

}

class B extends A {}

class X {
    doSomething() {
        super.doSomething();
        console.log('2 logSomethingElse');
    }
}

B.prototype.doSomething = X.prototype.doSomething;

In this case I'll get TypeError: (intermediate value).doSomething is not a function.

Is there any way to define methods (that refer to super) outside from the original class definition, and add these methods later to the original class?

Upvotes: 5

Views: 2255

Answers (3)

Estus Flask
Estus Flask

Reputation: 222369

super refers to ancestor of a class where the method was defined, it isn't dynamic. As Babel output illustrates this, super is hard-coded to Object.getPrototypeOf(X.prototype), and thus orphan class like this one doesn't make sense because it doesn't have super:

class X {
    doSomething() {
        super.doSomething();
        ...
    }
}

But super can be substituted with dynamic counterpart:

doSomething() {
    const dynamicSuper = Object.getPrototypeOf(this.constructor.prototype);
    // or
    // const dynamicSuper = Object.getPrototypeOf(Object.getPrototypeOf(this));
    dynamicSuper.doSomething();
    ...
}

class B extends A {}
B.prototype.doSomething = doSomething;

In this case it will refer to ancestor class of class instance where doSomething was assigned as prototype method.

Upvotes: 9

Hitmands
Hitmands

Reputation: 14169

While I think this could be assumed as anti-pattern, you shouldn't use super outside from a class.

You can achieve that using Object Literals.

Refer to Object.setPrototypeOf

const A = {
  sayHello() {
    console.log("I am A");
  },
  
  Factory() {
    return Object.create(this);
  }
}

const B = {
  sayHello() {
   super.sayHello();
  }
}

Object.setPrototypeOf(B, A);

const c = B.Factory();

c.sayHello();

Upvotes: 1

Kulvar
Kulvar

Reputation: 1179

If you don't make class X inherit from class B or A, the only way to call the method is A.prototype.doSomething() or more generally A.prototype.doSomething.call(this_substitute, ...args).

Upvotes: -2

Related Questions