在 class 中声明之前调用常规函数与箭头函数

Calling regular function vs. arrow function before their declaration in a class

如果我这样写 React class:

class SomeClass extends React.Component {
    state = {
        someState: this.someRegularFunction(),
        someOtherState: this.someArrowFunction()
    };

    someRegularFunction() {
        return "someText";
    }

    someArrowFunction = () => {
        return "someOtherText";
    };
}

Webstorm代码求助提示箭头函数调用this.someArrowFunction()说:

Field 'someArrowFunction' is declared after 'state' and is possibly not assigned yet

If 不警告调用常规函数 this.someRegularFunction()

而且 Webstorm 是正确的,调用 this.someArrowFunction() 时执行失败:

TypeError: _this.someArrowFunction is not a function


我一直在寻找一些解释此行为的文档,但找不到任何文档。

为什么在 class 中的声明之前可以调用常规函数,但不能调用箭头函数?

因为该代码在功能上与此相同:

class SomeClass extends React.Component {
    constructor(...args) {
        super(...args);
        this.state = {
            someState: this.someRegularFunction(),
            someOtherState: this.someArrowFunction()
        };
        this.someArrowFunction = () => {
            return "someOtherText";
        };
    }

    someRegularFunction() {
        return "someText";
    }
}

创建 实例 时,字段定义按源代码顺序处理。就好像它们是在任何其他代码之前(在基 class 中)或在调用 super 之后(在子 class 中)插入到构造函数中一样。

相比之下,someRegularFunction是原型的一个方法,它是在评估class定义时创建的,而不是稍后创建实例时创建的。

规范文本中的 the proposal for the class fields feature 涵盖了这一点。 (不过,阅读规范文本不适合胆小的人!:-))


旁注:这可以说是一种风格问题,但是如果你正在做那个箭头函数以便它可以使用 this 而你不必担心它是如何被调用的(例如,作为事件处理程序) ,您可能会考虑使其成为一个方法,然后在构造函数中(或实际上在构造函数中)使用 bind 代替:

class SomeClass extends React.Component {
    someFunction = this.someFunction.bind(this);
    state = {
        someState: this.someRegularFunction(),
        someOtherState: this.someFunction()
    };

    someRegularFunction() {
        return "someText";
    }

    someFunction() {
        return "someOtherText";
    }
}

这更适合可能需要模拟函数的测试代码(通过在原型上替换它)。

但同样,这可以说是风格问题。