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

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

我想创建一个包装器机制:我们包装 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。我知道我可以使用组合,但我想了解错误的来源。

您想使用 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

Why does the error happen?

因为使用superW.prototype.f方法只关心W.prototype的原型来评估super将引用什么。 super关键字本质上是一个静态查找,依赖于声明该方法的对象,忽略调用该方法的对象的原型链。

如果我们translate

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(这与使用 Object.setPrototypeOf(W.prototype, C.prototype) 的结果相同)。