【问题标题】:Why is arrow syntax preferred over function declaration for functional React components?为什么功能性 React 组件的箭头语法优于函数声明?
【发布时间】:2018-08-24 15:49:23
【问题描述】:

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

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

export default foo;

而不是更传统的函数声明语法:

function foo() {
  return ...;
}

export default foo;

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

【问题讨论】:

  • 看起来酷多了
  • 需要引用 :) 我认为这是基于意见的,我们可能只是在谈论开发人员的个人喜好。
  • 这是在炒作中流行起来的不良做法之一。 React 社区开始这样做了,突然大家都跟了上去。尽管有几个原因表明它应该被视为反模式并且应该首选正常的函数声明。
  • 查看这篇文章:sitepoint.com/…
  • 值得一提的是official React documentation使用的是传统的function

标签: javascript reactjs ecmascript-6


【解决方案1】:

我会说这确实是一个有点自以为是的选择。 (个人)认为将箭头函数用于纯功能组件是非常糟糕的做法,至少有几个原因。以下是那些:

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

  2. 错误堆栈跟踪。箭头函数中抛出的异常描述性较差,因为箭头函数根据定义是匿名的。这可能不是什么大问题,因为 React 项目很可能会配置适当的源映射支持,但如果使用命名函数,堆栈跟踪仍然会更加清晰。 正如 cmets 中所述,这并不是真正的功能组件的问题,因为名称基本上是变量的名称。

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

    const Header = ({ name, branding }) => (
      <header>
        ...
      </header>
    )
    

在上面的函数中,不可能快速抛出debugger 语句或console.log。您将不得不暂时将其转换为类似的东西

const Header = function ({ name, branding }) { 
  console.log(name)
  return (
    <header>
      ...
    </header>
  )
}

这可能很烦人,尤其是对于更大的纯函数组件。

话虽如此,这对于许多团队来说是一个非常受欢迎的选择,默认情况下也是 ESLint 的首选,所以如果你没有发现它的问题,那么它可能没问题。

【讨论】:

  • 我将在这个特定示例的情况下竞争#2。在某些情况下这是一个问题,但在这里它会从分配的绑定中获取名称:stackoverflow.com/questions/32828698/…
  • @loganfsmyth 你是绝对正确的。那么第2点确实不是问题,我想我把这个问题与在回调中使用箭头函数混淆了,比如地图等。
  • 是的,对回调来说绝对是个烦恼:(
  • @dfsq 3 也不太适用。对多行函数执行此操作肯定更方便(临时变量有很大帮助),但您始终可以将 console.log(),eval('debugger'), 放入单行箭头(请注意,React 函数组件已经有 (...) 。此外,这不是关于常规函数与箭头函数,而是关于隐式与显式返回。但关于调试的重要一点是,您在常规函数中有arguments(但箭头也会在 ES5 目标中具有它)。
  • @wmp224 哦,我明白了,我们在谈论不同的事情。当然可以。我说的是短返回符号。
【解决方案2】:

其实它们之间没有区别,我在CodeSandBox上做了一个little project,并做了两个简单的组件,其中一个是Arrow组件,使用箭头函数: p>

import React from 'react';

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

export default MyArrowComponent;

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

import React from "react";

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

export default MyFunctionComponent;

然后我运行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]]]);

注意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"))
}

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

【讨论】:

    【解决方案3】:

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

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

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

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

    更多细节,你可以看看这些问题

    When should I use Arrow functions in ECMAScript 6?

    【讨论】:

    • this 绑定与未附加到对象的函数无关。
    • 澄清-信用到期:上面列出的3点来自lyschoening's answer mentioned in the question link above
    • 我不同意它“更容易阅读”。我们从左到右、从上到下阅读,function 的使用可以很容易地识别函数声明与变量声明,而无需在视觉上向右扫描。我绝对讨厌阅读左侧直接const 的文件,因为它需要向右扫描以确定它是函数还是变量。使用function 关键字可以更轻松地从上到下扫描代码,而无需从左到右扫描。
    【解决方案4】:

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

    如果您将使用箭头函数或函数声明,请尝试考虑在上下文中更有意义的内容。为了使代码更简洁、更易于阅读,这不仅与您编写的代码量有关,还与代码表达的内容有关。

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

    【讨论】:

      猜你喜欢
      • 2020-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-23
      • 1970-01-01
      • 2020-01-12
      • 2020-01-22
      • 2019-06-17
      相关资源
      最近更新 更多