为什么箭头语法优于纯React组件的标准函数?

Phi*_*son 9 javascript ecmascript-6 reactjs

我总是看到用箭头函数语法定义的纯React组件的示例:

const foo = () => (...);

export default foo;
Run Code Online (Sandbox Code Playgroud)

而不是更传统的函数定义语法:

function foo() {
  return ...;
}

export default foo;
Run Code Online (Sandbox Code Playgroud)

是否有理由更喜欢前者而不是后者?

Fer*_*uza 11

函数声明和箭头函数本质上是不同的,但在您的问题范围内,它基本上是代码风格偏好。我个人更喜欢函数声明,因为我发现更容易发现该行代码的含义。

如果您将使用箭头函数或函数声明,请尝试考虑在上下文中什么更有意义。为了使代码干净且易于阅读,不仅取决于您编写的代码量,还取决于代码表达的内容。

我倾向于使用箭头函数进行回调,例如,[].map(() => {})


dfs*_*fsq 9

我会说这是一个有点自以为是的选择.至少有几个原因导致(个人)将箭头功能用于纯功能组件作为非常糟糕的做法.这些是:

  1. 语法滥用.当我们定义函数组件时,我们不需要将其上下文预绑定到特定范围.context(this)undefined无论如何都要在模块命名空间中.箭头功能的使用在这里由纯粹的美学原因决定,如简洁.但箭头作为语言特征的功能首先存在非常具体的目的,这不是冷静和简洁.

  2. 错误堆栈跟踪.箭头函数中抛出的异常将不那么具有描述性,因为箭头函数的定义是匿名的.这可能不是一个大问题,因为React项目很可能配置了适当的源映射支持,但如果使用了命名函数,堆栈跟踪仍然会更清楚一些.正如评论中所指出的,这不是功能组件的问题,因为名称基本上是变量的名称.

  3. 记录不太方便.考虑这种非常典型的纯函数组件样式:

    const Header = ({ name, branding }) => (
      <header>
        ...
      </header>
    )
    
    Run Code Online (Sandbox Code Playgroud)

在上面的函数中,不可能快速debugger声明或console.log.你必须暂时将它转换成这样的东西

const Header = function ({ name, branding }) { 
  console.log(name)
  return (
    <header>
      ...
    </header>
  )
}
Run Code Online (Sandbox Code Playgroud)

这对于更大的纯组件来说可能非常烦人.

这就是说这是很多团队非常受欢迎的选择,默认情况下也是ESLint的首选,所以如果你没有看到它的问题,那么它可能没关系.

  • @IvanKleshnin 组件定义不需要简洁。如果有的话,优先考虑的应该是清晰而不是简洁。谁在编写 1-2 行函数式比较(完全),然后因为隐式返回而感觉良好?人们这样做 b/c FB 这样做并且 ESLint 默认它。尝试阅读一个 ES6 模块,其中*所有*都被定义为 const...这种区别很有价值。更不用说方法签名实际上需要*更多*击键并且由于 = 和 =&gt; 而本质上更繁忙。箭头表示法是一项功能,应谨慎使用。 (2认同)

eto*_*xin 8

其他答案中没有提到的其他几点:

  • 对于箭头函数组件,当在 Chrome/Firefox 中使用 React 开发工具时,这些组件会导致Anonymous调试变得更加困难。这些匿名组件也存在于整个开发工具中,包括性能火焰树。功能组件在开发工具中显示其名称。
  • 标准函数声明可以在一行上定义。您不需要export default在文件中定义后者。当您想要添加/删除关键字时,这也使您变得更容易default
export default async function MyComponent() {
  ...
}
Run Code Online (Sandbox Code Playgroud)


Ame*_*icA 6

其实它们没有区别,我在CodeSandBox上做了一个小项目,做了两个简单的组件,其中一个是Arrow使用箭头函数的组件:

import React from 'react';

const MyArrowComponent = () => (
  <main>
    <h2>Arrow</h2>
  </main>
);

export default MyArrowComponent;
Run Code Online (Sandbox Code Playgroud)

另一个是Declaration使用函数声明的组件:

import React from "react";

function MyFunctionComponent() {
    return (
        <main>
            <h2>Declaration</h2>
        </main>
    );
}

export default MyFunctionComponent;
Run Code Online (Sandbox Code Playgroud)

然后我运行yarn build命令并得到如下所示的包:

(window.webpackJsonp = window.webpackJsonp || []).push([[0], {
  14: function (e, n, t) {
    "use strict";
    t.r(n);
    var a = t(0), r = t.n(a), l = t(2),
        c = t.n(l), u = t(3), i = t(4), o = t(6), m = t(5), E = t(7);
    var p = function () {
      return r.a.createElement("main", null, r.a.createElement("h2", null, "Declaration"))
    }, s = function () {
      return r.a.createElement("main", null, r.a.createElement("h2", null, "Arrow"))
    }, d = function (e) {
      function n() {
            return (
              Object(u.a)(this, n),
              Object(o.a)(this, Object(m.a)(n).apply(this, arguments))
      }
      return Object(E.a)(n, e), Object(i.a)(n, [{
        key: "render", value: function () {
          return r.a.createElement(
            'div',
            null,
            r.a.createElement('div', null, 'Hi'),
            r.a.createElement(p, null),
            r.a.createElement(s, null)
          );
        }
      }]), n
    }(r.a.Component);
    c.a.render(r.a.createElement(d, null), document.getElementById("root"))
  }, 8: function (e, n, t) {
    e.exports = t(14)
  }
}, [[8, 1, 2]]]);
Run Code Online (Sandbox Code Playgroud)

注意组件ArrowDeclaration组件的定义:

var p = function () {
  return r.a.createElement("main", null, r.a.createElement("h2", null, "Declaration"))
}, s = function () {
  return r.a.createElement("main", null, r.a.createElement("h2", null, "Arrow"))
}
Run Code Online (Sandbox Code Playgroud)

两者的定义都是一样的,所以肯定没有区别,完全基于开发者对代码可读性和代码整洁的态度,我们团队基于ESLint 5.x我们选择箭头函数来定义功能组件。


Abd*_*rif 4

使用箭头函数比使用常规函数要好得多,不仅因为语法干净并且您可以使用箭头函数编写更少的代码,还因为:

  1. 作用域安全:当箭头函数一致使用时,一切都保证使用相同的 thisObject 作为根。如果即使是一个标准函数回调与一堆箭头函数混合在一起,作用域就有可能变得混乱。

  2. 紧凑性:箭头函数更易于阅读和编写。

  3. 清晰度:当几乎所有东西都是箭头函数时,任何常规函数都会立即突出来定义范围。开发人员始终可以查找下一个更高的函数语句来查看该对象是什么。

欲了解更多详细信息,您可以查看这些问题

我什么时候应该在 ECMAScript 6 中使用箭头函数?

  • 我不同意它“更容易阅读”。我们从左到右、从上到下阅读,使用“function”可以轻松识别函数声明和变量声明,而无需从视觉上向右扫描。我绝对讨厌读取左侧直接“const”的文件,因为它需要向右扫描以确定它是函数还是变量。使用“function”关键字使代码更容易从上到下扫描,而无需从左到右扫描。 (25认同)
  • “this”绑定与未附加到对象的函数无关。 (15认同)
  • “紧凑性”似乎是一个错误的术语。`export const Component = () =&gt; {...};` 实际上比 `export function Component() {...}` 长 (6认同)
  • 1.您所说的这种“安全”仅对方法(从对象调用的函数)有用。功能组件不依赖于对象,并且“this”关键字属于模块本身的范围,它将是未定义的或指向窗口或文档对象(我不确定React和Babel如何定义它) )。2. 我认为使用虚词从左到右阅读实际上更容易阅读。箭头函数增加了一层额外的语法复杂性。我同意箭头函数要“酷得多”。 (3认同)