【问题标题】:Accessing a class field on a superclass访问超类上的类字段
【发布时间】:2019-03-20 05:59:20
【问题描述】:

我有一个包含以下代码的文件:

class Animal {
    doSomething = () => {
        return 'Hi.';
    };
}

class Dog extends Animal {
    doSomething = () => {
        return super.doSomething() + ' Woof!';
    };
}

console.log(new Dog().doSomething());

注意:尝试运行上面的 sn-p 可能行不通,因为我不知道如何使它使用我的 Babal 设置。

无论如何,当我使用 Babel 编译它并在 Node 中运行它时,我收到以下错误:

/Users/elias/src/classFieldTest/build/classFieldTest.js:15
            return super.doSomething() + ' Woof!';
                         ^

TypeError: (intermediate value).doSomething is not a function
    at Dog.doSomething (/Users/elias/src/classFieldTest/build/classFieldTest.js:15:26)
    at Object.<anonymous> (/Users/elias/src/classFieldTest/build/classFieldTest.js:21:23)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Function.Module.runMain (module.js:693:10)
    at startup (bootstrap_node.js:188:16)
    at bootstrap_node.js:609:3

我正在使用带有 stage-2 预设的 Babel 6.26.0 和 Node 8.11.1。如果有人关心,我可以展示我正在使用的命令。

为什么会这样?我猜super 不能用于访问类字段,但我该怎么做呢?如果我将AnimaldoSomething 方法更改为传统方法(doSomething() { return 'Hi.'; }),它可以工作,但我宁愿避免传统方法,用他们重新定义this 的方式以及它引起的所有混乱。

有没有办法访问超类的类字段?

【问题讨论】:

  • 投反对票是为了什么???
  • "他们重新定义 this 的方式及其引起的所有混乱" - 了解 this 的动态本质应该是使用 class 之前的第一步句法。如果 ´this` 关键字仍然引起混乱,请不要使用箭头函数。
  • “如果 'this' 关键字仍然引起混乱,请不要使用箭头函数”。为什么?箭头函数的一个主要优点是它们不会重新定义this。以我的经验,在定义它的对象上调用方法是人们通常想要做的事情,而在另一个对象上调用它只是很少需要的。我知道this-rebinding 是如何工作的,但是在将方法传递给setTimeout(例如)时出现错误仍然很烦人,这可能会导致经验不足的程序员感到困惑。
  • 方法通常在原型对象上定义,然后在从它继承的对象上调用 - 这是规则而不是例外。此外,super 本身就是这样工作的——你想在你的子类实例上调用超类中定义的方法!与其试图避免this,不如教育经验不足的程序员。

标签: javascript babeljs arrow-functions ecmascript-next class-fields


【解决方案1】:

为什么会这样?我猜 super 不能用于访问类字段

是的。类字段是实例属性,但super 尝试访问超类的原型对象上的属性。您的 Animal 类根本没有 doSomething 方法 - 相反,每个 Animal 对象都有一个包含绑定函数的属性。

但是我应该怎么做呢?如果我将其更改为传统方法,它可以工作

是的,你应该这样做。这就是方法和super 的工作方式。

避免使用箭头函数when you don't need them,尤其是when they don't work。也可以看看Arrow Functions in Class Properties Might Not Be As Great As We Think

有没有办法访问超类的类字段?

是的 - 它是一个实例属性,您可以在覆盖之前在构造函数中访问它:

class Animal {
    constructor() {
        this.doSomething = () => {
             return 'Hi.';
        };
    }
}

class Dog extends Animal {
    constructor() {
        super();
        const superDoSomething = this.doSomething;
        this.doSomething = () => {
            return superDoSomething() + ' Woof!';
        };
    }
}

或者,使用类字段提案并且没有显式构造函数:

class Animal {
    doSomething = () => {
        return 'Hi.';
    }
}

class Dog extends Animal {
    doSomething = (superDoSomething => () => {
        return superDoSomething() + ' Woof!';
    })(this.doSomething)
}

【讨论】:

  • 谢谢。我试过你的superDoSomething 想法。这有点奇怪,但它确实有效,这是迄今为止我能想到的最好的东西。
  • 当然很奇怪,但如果你坚持使用箭头函数作为实例属性,这是你唯一能做的……
猜你喜欢
  • 1970-01-01
  • 2013-05-27
  • 1970-01-01
  • 1970-01-01
  • 2015-09-24
  • 1970-01-01
  • 2021-09-09
  • 1970-01-01
  • 2015-03-26
相关资源
最近更新 更多