0

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.

Kuraga
  • 331
  • 3
  • 16
  • possible a duplicate of, https://stackoverflow.com/questions/2107556/how-to-inherit-from-a-class-in-javascript ... read it there, it might solve your problem. – gugateider Oct 03 '18 at 14:20
  • @gugateider thanks but sorry, i don't see an answer there – Kuraga Oct 03 '18 at 14:42
  • 1
    What `obj` do you want to wrap? There is no `obj` variable in the code you posted. – Bergi Oct 03 '18 at 15:36
  • 1
    Have a look at [this](https://stackoverflow.com/a/49822270/1048572) and [that](https://stackoverflow.com/a/27511897/1048572) – Bergi Oct 03 '18 at 15:38
  • Update: P.S. I do understand that I could use composition but I want to understand the source of error. – Kuraga Oct 03 '18 at 17:00
  • @Bergi, `c`. Thanks for links. But why is error happen? I don't see there... – Kuraga Oct 03 '18 at 17:01
  • @JakeHolzinger 'The `super` keyword requires the `extends` keyword' - from ECMAScript standard? – Kuraga Oct 03 '18 at 17:45

2 Answers2

1

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)).

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Ahhh, I forget that `f` is not `W.f` but `W.prototype.f`... Now I see al the chain! Thanks very much! :) – Kuraga Oct 03 '18 at 17:54
0

you want to use the extends keyword for example:

    class C {
        f() { console.log( "C.f" ); }
    }

    class W extends C {
        f() {
            super.f()
            console.log( "W.f" );
        }
    }

    const w = new W();
    w.f(); // will output C.f W.f
Ben Randle
  • 11
  • 2
  • No. Object `c` is given by call of external llibrary's function. It's properties are not accessible in your code. We can use composition. But that's another story... – Kuraga Oct 03 '18 at 16:47