Search code examples
javascriptoopinheritanceecmascript-6super

Access parent (super) method in object created by Object.create


I want to create a wrapper mechanism: we wrap c so new new object w has own properties and methods but c's are also accessible.

// Note: this class might be from an external lib
class C {
  f() {
    console.log('f (original)');
    this.p = 'p';
  }
}

class W {
  f() {
    console.log('f (new)');
    super.f();  // TypeError: (intermediate value).f is not a function
    console.log(this.p);
  }
}

// Note: this value is external for us
const c = new C();

const w = Object.create(null, Object.getOwnPropertyDescriptors(W.prototype));
Object.setPrototypeOf(w, c);

w.f();  // expected:
        // f (new)
        // f (original)
        // p

Do I do this in correct manner?

Why is error happen?

Update: P.S. I do understand that I could use composition but I want to understand the source of error.


Solution

  • Why does the error happen?

    Because the W.prototype.f method that uses super only cares about the prototype of W.prototype to evaluate what super will refer to. The super keyword is essentially a static lookup, depending on the object in which the method was declared, ignoring the prototype chain of the object that the method was called on.

    If we translate to

    class W {
      f() {
        console.log('f (new)');
        Object.getPrototypeOf(W.prototype).f.call(this); // TypeError: (intermediate value).f is not a function
        console.log(this.p);
      }
    }
    

    we can see that Object.prototype.f is not a function…


    So you could fix the issue by doing Object.setPrototypeOf(W.prototype, C.prototype) instead of Object.setPrototypeOf(w, c) (or w = Object.create(c, …)), but I can't recommend that. If you really wanted to affect all instances, you'd have written class W extends C already (which would have the same result as using Object.setPrototypeOf(W.prototype, C.prototype)).