【问题标题】:ES6 use `super` out of class definitionES6 使用 `super` 超出类定义
【发布时间】:2017-10-18 08:44:04
【问题描述】:

我正在尝试向类中添加额外的方法,这些额外的方法应该使用super 方法。

如果我将它们添加到模型定义中,它会起作用。

class A {
    doSomething() {
        console.log('logSomething');
    }

}

class B extends A {
    doSomething() {
        super.doSomething();
        console.log('logSomethingElse');
    }
}

如果我尝试将额外的方法添加到B.prototype,我会得到SyntaxError: 'super' keyword unexpected here

class A {
    doSomething() {
        console.log('logSomething');
    }

}

class B extends A {
}

B.prototype.doSomething = function doSomething() {
    super.doSomething();
    console.log('logSomethingElse');
}

很清楚,为什么我会收到此错误。这是一个函数而不是类方法。

我们尝试将方法定义为类方法,并将其复制到原来的B类中:

class A {
    doSomething() {
        console.log('logSomething');
    }

}

class B extends A {}

class X {
    doSomething() {
        super.doSomething();
        console.log('2 logSomethingElse');
    }
}

B.prototype.doSomething = X.prototype.doSomething;

在这种情况下,我会收到TypeError: (intermediate value).doSomething is not a function

有没有办法在原始类定义之外定义方法(引用super),然后将这些方法添加到原始类中?

【问题讨论】:

标签: javascript class ecmascript-6


【解决方案1】:

super 指的是定义方法的类的祖先,它不是动态的。正如Babel output 说明的那样,super 被硬编码为Object.getPrototypeOf(X.prototype),因此像这样的孤儿类没有意义,因为它没有super

class X {
    doSomething() {
        super.doSomething();
        ...
    }
}

super 可以替换为动态对应项:

doSomething() {
    const dynamicSuper = Object.getPrototypeOf(this.constructor.prototype);
    // or
    // const dynamicSuper = Object.getPrototypeOf(Object.getPrototypeOf(this));
    dynamicSuper.doSomething();
    ...
}

class B extends A {}
B.prototype.doSomething = doSomething;

在这种情况下,它将引用类实例的祖先类,其中 doSomething 被分配为原型方法。

【讨论】:

  • > dynamicSuper repl.it/MrdK。获得超级的唯一安全方法是静态的。 const staticSuper = Object.getPrototypeOf(X.prototype);
  • @JeffM 即使我不(我真的不),这就是问题的答案。当然,开发人员在处理原型链时应该知道他/她在做什么。
【解决方案2】:

虽然我认为这可以被认为是反模式,但您不应该在class 之外使用super

您可以使用Object Literals 来实现。

参考Object.setPrototypeOf

const A = {
  sayHello() {
    console.log("I am A");
  },
  
  Factory() {
    return Object.create(this);
  }
}

const B = {
  sayHello() {
   super.sayHello();
  }
}

Object.setPrototypeOf(B, A);

const c = B.Factory();

c.sayHello();

【讨论】:

    【解决方案3】:

    如果您不让类 X 继承自类 B 或 A,则调用该方法的唯一方法是 A.prototype.doSomething() 或更一般的 A.prototype.doSomething.call(this_substitute, ...args)

    【讨论】:

    • 但是在我定义X 的地方,没有A,因为我可能想将此方法添加到多个类中。当我定义X.doSomething时,我不知道哪个类将是super
    • 对于不绑定到特定类的函数,不要将其定义为方法。只需执行常规功能。如果您需要“this”值,请将其作为第一个参数。
    • 我不需要this。我需要super
    • super 只是一种访问父类的方法。如果没有父类,super 没用。
    猜你喜欢
    • 1970-01-01
    • 2017-05-23
    • 1970-01-01
    • 2017-10-24
    • 2018-02-13
    • 2015-09-13
    相关资源
    最近更新 更多