React:哪个是推荐的箭头或正常功能?

React: Which is recommended arrow or normal function?

我开始使用箭头函数是因为我觉得手动 function/object 绑定和范围相关的问题很头疼,但最近我开始知道使用普通函数 (ES5) 比使用箭头函数 (ES6) 更好.

我对这些函数的理解

React 中的正常功能:

  1. Bind object/function manually in order to play with state or props inside the function and to avoid scope related issues
  2. Bind object/function always in constructor but not directly in render
  3. If you do it in constructor then Webpack creates new object/function in bundle.js file only once when your component renders for the first time
  4. If you do it directly in render then Webpack will create a new object/function in bundle.js file every time your component renders and re-renders
  5. If you don’t bind then you can’t access state or props. You have to assign current object to a local variable otherwise this.state or this.props is undefined

React 中的箭头函数:

  1. No need to bind an object/function in constructor nor render
  2. You no need to depend on local variable interms of current object i.e., let that = this;
  3. You will not have scope issues and object/function binding takes automatically

但我的疑问是,我听说建议使用普通函数并将其绑定在构造函数中,而不是使用箭头函数,因为每次你的组件时,箭头函数都会在 Webpack bundle.js 中创建新的 object/function渲染和重新渲染。

Is this true? Which is Recommended?

此线程接受的答案 说 —> 这取决于您使用箭头功能的确切位置。如果在 render 方法中使用 Arrow 函数,那么每次调用 render 时它们都会创建一个新实例,就像 bind 的工作方式一样。

对不起,如果你觉得这是一个戏剧性的问题,但这是我最大的疑问。请推荐

如果您有以下 React 代码,

class A extends React.Component {
  constructor(props) {
    super(props)
    this.state = {name: props.name}
  }
  render() {
    return (
       <button onclick={(event)=>console.log(this.state.name)} />
    )
  }
}

改为关注

class A extends React.Component {
  state = {name: this.props.name}
  render() {
    return (
       <button onclick={this.logName} />
    )
  }
  logName = (event) => {
    console.log(this.state.name)
  }
}

这样,您就不会在每次渲染时都创建新的匿名函数。

每次你有代码时都会创建新的函数实例 运行ning ()=>,这不是magic。看看下面的成员函数

class A {
  memberFuncWithBinding = () => {}
  memberFuncWithoutBinding(){}
}

这两个成员函数只在 class 实例化时创建一次。同样,没有魔法,但是上层成员函数是首选,因为在该函数内部使用 this 时,您将拥有正确的 class A this 绑定。

编辑:看,在 运行 遇到问题之前不要尝试优化代码。每次渲染创建新函数都比较慢,但只有几分之一毫秒。

周围有很多答案,但人们总是感到困惑。我知道这一点,因为我前一段时间感到困惑。一段时间后,我掌握了这些概念。

  1. Bind object/function manually in order to play with state or props inside the function and to avoid scope-related issues

不完全正确。您无需绑定函数即可使用状态或道具。当您在作用域中丢失 this 上下文时,您将函数绑定到 this。例如在回调函数中。

class App extends React.Component {
  state = {
    name: "foo",
  }
  aFunction() {
    console.log( this.state.name );
  }
  render() {
    return <div>{this.aFunction()}</div>;
  }
}

您不需要绑定您的函数,因为 this 指向您的 class 并且您不会丢失它的上下文。但是如果你像按钮一样在回调中使用你的函数,你必须绑定它:

class App extends React.Component {
  state = {
    name: "foo",
  }
  aFunction() {
    console.log( this.state.name );
  }

  render() {
    return (
      <div>
        <button onClick={this.aFunction}>Click</button>
      </div>
    );
  }
}

这不起作用,因为您失去了上下文。现在,您需要以某种方式取回它的上下文吗?好的,让我们看看我们如何做到这一点。首先,我想在按钮回调中绑定它。

<button onClick={this.aFunction.bind(this)}>Click</button>

是的,这行得通。但是,它将在每次渲染中重新创建。所以:

  1. Bind object/function always in constructor but not directly in render

是的。不要像我上面那样绑定它,在你的构造函数中做。

  1. If you do it in constructor then Webpack creates new object/function in bundle.js file only once when your component renders for the first time

  2. If you do it directly in render then Webpack will create a new object/function in bundle.js file every time your component renders and re-render

你在这里总结了我迄今为止试图解释的内容。但是,我想 Webpack 不是这样做的,你的应用程序是。

  1. If you don’t bind then you can’t access state or props. You have to assign current object to a local variable otherwise this.state or this.props is undefined

同样,如果您在 class 范围内使用函数,则不必绑定它。如果您在 class 之外使用此功能,例如按钮回调,则必须绑定它。这与 stateprops 无关。这与使用 this 有关。

您的第二个绑定选项是使用常规函数在构造函数中进行绑定,第三个选项是使用不带绑定的箭头函数。

现在,箭头函数。

1.No need to bind an object/function in constructor nor render

是的。

  1. You no need to depend on local variable interms of current object i.e., let that = this;

是的。

  1. You will not have scope issues and object/function binding takes automatically

是的。

But my query is that I heard that it’s recommended to use normal function and bind it in constructor rather than using arrow function because arrow functions create new object/function in Webpack bundle.js every time your component renders & re-renders.

正如大家所说,这取决于你在哪里使用它们。

render() {
    return (
        <div>
            <button onClick={() => this.aFunction()}>Click</button>
        </div>
    );
}

在这里,它将在每次渲染中重新创建。但是如果你不需要传递任何参数给它,你可以通过引用使用它。

render() {
    return (
        <div>
            <button onClick={this.aFunction}>Click</button>
        </div>
    );
}

这与上一个一样。因此,如果您在渲染方法中看到 (),则该函数会在每次渲染中重新创建。常规或箭头一,没关系。如果您以某种方式调用它,那么您就是在重新创建它。这适用于像 aFunction.bind(this) 这样的渲染中的绑定。我在那里看到 ()

所以,通过引用使用函数可以避免这个问题。现在,最大的问题是当我们需要一些参数时会发生什么?如果您使用箭头函数传递参数,请尝试更改您的逻辑。

但这真的那么重要吗?正如@Eric Kim 所说,如果您确实需要优化,那么优化就是一个问题。这是一个普遍的建议,因为我从很多人那里听说过。但就个人而言,如果函数将在每次渲染中重新创建,我会尽量避免使用它们。但同样,这完全是个人的。

你怎么能改变你的逻辑?您正在用一个项目映射一个数组并创建 一个按钮。在此按钮中,您使用的是将项目名称传递给函数的函数。

{
    items.map( item =>
        <button onClick={() => this.aFunction(item.name)}>Click</button>
    )
}

此函数将在每个项目的每次渲染中重新创建!所以,改变你的逻辑,创建一个单独的 Item 组件并映射它。将 itemaFunction 作为 props 传递。然后在这个组件中使用处理函数使用你的函数。

const Item = ( props ) => {
    const handleClick = () => props.aFunction( props.item.name );
    return (
        <button onClick={handleClick}>Click</button>
    );
}

在这里,您使用的是 onClick 处理程序及其引用,它会调用您的实际函数。不会在每次渲染中重新创建函数。但是,不利的是,您需要编写一个单独的组件和更多的代码。

大多数时候您都可以应用此逻辑。也许会有一些你做不到的例子,谁知道呢。所以决定权在你。

顺便说一句,@widged 在评论中给出的 Medium post 是关于这个问题的著名讨论。箭头函数真的比普通函数慢吗?是的。但是多少钱?我猜没那么多。此外,对于转译后的代码也是如此。以后变成原生的时候,就是速度更快的了。

作为个人旁注。我一直在使用箭头函数,因为我喜欢它们。不过前段时间在讨论中,有人说

When I see an arrow function in the class I think that: 'This function is being used/called outside of this class'. If I see a regular one I understand that this function called inside the class.

我真的很喜欢这种方法,现在如果我不需要在 class 之外调用我的函数,我会使用常规方法。