【问题标题】:What is the difference between arrow functions and regular functions inside React functional components (no longer using class components)?React 函数式组件(不再使用类组件)中的箭头函数和常规函数有什么区别?
【发布时间】:2019-09-21 22:29:32
【问题描述】:

自从 React Hooks 以来,我决定放弃 React 类组件。我现在只处理钩子和功能组件。

简单问题:

我了解在类体内使用箭头函数而不是常规函数之间的区别。箭头函数会自动将 (lexical this) 绑定到我的类的实例,我不必在构造函数中绑定它。这个不错。

但由于我不再处理类,我想知道在功能组件内部执行以下操作有什么区别:

function App() {

  // REGULAR FUNCTION
  function handleClick1() {
    console.log('handleClick1 executed...');
  }

  // ARROW FUNCTION
  const handleClick2 = () => {
    console.log('handleClick2 executed...');
  }

  return(
    <React.Fragment>
      <div className={'div1'} onClick={handleClick1}>
        Div 1 - Click me
      </div>
      <div className={'div2'} onClick={handleClick2}>
        Div 2 - Click me
      </div>
    </React.Fragment>
  );
}

问题

两者都可以正常工作。

性能是否存在差异?我应该选择一种方式而不是另一种方式吗?它们在每次渲染时都会重新创建,对吗?强>


可能重复的注意事项

我真的不认为这是一个重复的问题。我知道关于箭头和正则之间的区别有很多问题,但我想从 React 功能组件的角度了解 React 如何处理它。我环顾四周,没有找到。


用于测试的代码片段

function App() {
  
  function handleClick1() {
    console.log('handleClick1 executed...');
  }
  
  const handleClick2 = () => {
    console.log('handleClick2 executed...');
  }
  
  return(
    <React.Fragment>
      <div className={'div1'} onClick={handleClick1}>
        Div 1 - Click me
      </div>
      <div className={'div2'} onClick={handleClick2}>
        Div 2 - Click me
      </div>
    </React.Fragment>
  );
}

ReactDOM.render(<App/>, document.getElementById('root'));
.div1 {
  border: 1px solid blue;
  cursor: pointer;
}

.div2 {
  border: 1px solid blue;
  cursor: pointer;
 }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

【问题讨论】:

  • 如果您不使用this,那么函数内部的差异完全无关紧要。外部的区别在于函数声明被提升到范围的顶部,将箭头函数分配给变量(var,const,let)不是。 var 与 const 和 let 的不同之处还有进一步的区别,但只有在分配之前引用某些内容才重要。
  • 无论您阅读过关于箭头函数、常规命名函数还是使用变量声明的匿名函数的任何其他信息,这里仍然适用。 There is no performance difference 在他们之间。甚至无法在运行时检测函数是否为箭头函数,因此 React 不会也无法以不同于常规函数的方式处理它们。
  • 根据之前的评论,请参阅 thisthis
  • 哎呀。我错了无法检测箭头功能。 stackoverflow.com/questions/28222228/… 但我非常怀疑 React 是否会这样做。主要是因为转译器是一个东西。

标签: javascript reactjs react-hooks


【解决方案1】:

除了您已经指出的差异(词法范围)之外,箭头函数(和函数表达式)是提升的,因此在定义之前不能调用它们。看我的例子。我认为这不是问题,因为依赖于提升的代码更难推理。

React 真的不关心你使用的是哪一个(也无法检测到它)。

const A = () => {
  const name = getName();
  
  function getName() {
    return 'praffn';
  }
  
  // Will not work
  // const getName = () => 'praffn';
  
  return <p>Hi, {name}</p>;
}

ReactDOM.render(<A/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>

【讨论】:

  • 就我个人而言,我没有发现函数提升在实践中是一个很大的问题(与var 提升不同),我认为在此处使用function 关键字会使代码比实际更具可读性几乎所有内容都以const 开头。 (我怀疑 Facebook 可能有类似的原因在他们的示例中使用 function。)但正如 Phillip 已经指出的那样,这是一种风格偏好——两者都可以正常工作。
  • @MattBrowne,我实际上更喜欢使用function 关键字——对我来说它更具可读性。我通常只将箭头函数用于单行以及用于高阶函数时。但是,如果可能,我会尽量避免依赖提升。
  • @MattBrowne 我认为function 关键字也使代码更具可读性。而且我几乎从不使用吊装“功能”。
【解决方案2】:

由于您没有访问 this 上下文,因此两者的行为相同

要了解更多信息,您可以查看 babel 是如何传输到 ECMA 的:

 const handleClick2 = () => {
    console.log('handleClick2 executed...');
    this.x=3
 }

将被转译为:

"use strict";

var _this = void 0;

var handleClick2 = function handleClick2() {
  console.log('handleClick2 executed...');
  _this.x = 3;
};

Link to babel notepad

【讨论】:

  • 在箭头函数或函数声明中访问 this 不会有任何区别,因为 this 将等于 undefined。这是因为React components are written within ES6 modules, which automatically run in strict mode.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-22
  • 2020-04-04
  • 1970-01-01
  • 2021-02-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多