在Object.create创建的对象中访问父(超级)方法

时间:2018-10-03 14:02:15

标签: javascript oop inheritance ecmascript-6 super

我想创建一个包装器机制:我们包装c,以便新的新对象w拥有自己的属性和方法,但是c也可以访问。

// 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

我这样做是否正确?

为什么会发生错误?

更新:P.S.我确实知道我可以使用合成,但是我想了解错误的来源。

2 个答案:

答案 0 :(得分:1)

  

为什么会发生错误?

因为使用W.prototype.f的{​​{1}}方法只关心super的原型来评估W.prototype所引用的内容。 super关键字本质上是静态查找,具体取决于声明该方法的对象,而忽略了调用该方法的对象的原型链。

如果我们translate

super

我们可以看到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); } } 不是函数……


因此,您可以通过执行Object.prototype.f而不是Object.setPrototypeOf(W.prototype, C.prototype)(或Object.setPrototypeOf(w, c))来解决此问题,但我不建议这样做。如果您确实想影响所有实例,那么您已经编写了w = Object.create(c, …)(与使用class W extends C的结果相同)。

答案 1 :(得分:0)

例如,您要使用extends关键字:

    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