Search code examples
javascriptes6-classprototypal-inheritancejavascript-inheritance

Why I can't use 'super' in prototype method definition when I can use Object.getPrototypeOf(this.constructor.prototype)?


So I tested this code:

class C1 {}

C1.prototype. f =function(){ return 1 }

class C2 extends C1 {}

C2.prototype. f =function(){ return super.f()+1 }

And it throws a syntax error: 'super' keyword unexpected here.

But if I do:

C2.prototype. f =function(){ return Object.getPrototypeOf(this.constructor.prototype).f() + 1 }

It does return a two!

So does anyone know why 'super' doesn't work? I see no reason for it.

Thanks!


Solution

  • Object.getPrototypeOf(this.constructor.prototype).f() loses the instance:

    class C1 {
        constructor(x) {
            this.x = x;
        }
    
        f() {
            console.log(this.x);
        }
    }
    
    class C2 extends C1 {
        f() {
            Object.getPrototypeOf(this.constructor.prototype).f();
        }
    }
    
    new C1(42).f();  // 42
    new C2(42).f();  // undefined

    (because this === C1.prototype when a function is called as C1.prototype.f())

    Object.getPrototypeOf(this.constructor.prototype).f.call(this) always has this.constructor as the bottom of the class hierarchy, which breaks when you add a level:

    class C1 {
        constructor(x) {
            this.x = x;
        }
    
        f() {
            console.log(this.x);
        }
    }
    
    class C2 extends C1 {
        f() {
            Object.getPrototypeOf(this.constructor.prototype).f.call(this);
        }
    }
    
    class C3 extends C2 {}
    
    new C1(42).f();  // 42
    new C2(42).f();  // 42
    new C3(42).f();  // infinite recursion

    A correct version for reasonable code would be

    Object.getPrototypeOf(/* containing class */.prototype).f.call(this)
    

    which is basically what super does – and for that, it needs to know the containing class (or object), which doesn’t necessarily exist for arbitrary function expressions.