ES6箭头函数中什么时候应该使用return语句?

204
新的ES6箭头函数表示在某些情况下return是隐式的:

该表达式也是该函数的隐式返回值。

我在什么情况下需要在ES6箭头函数中使用return
6个回答

318

Jackson在类似的问题中已经进行了部分回答:链接

如果没有代码块,则为隐式返回。

  • 当一行扩展到多行时,程序员忘记添加return会导致错误。
  • 隐式返回在语法上存在歧义。例如,(name) => {id: name}返回对象{id: name}吗?错了。它返回undefined。这些花括号是一个显式的代码块。 id: 是一个标签。

我要补充一下代码块的定义:

代码块用于组合零个或多个语句。代码块由一对花括号括起来。

示例

// returns: undefined
// explanation: an empty block with an implicit return
((name) => {})() 

// returns: 'Hi Jess'
// explanation: no block means implicit return
((name) => 'Hi ' + name)('Jess')

// returns: undefined
// explanation: explicit return required inside block, but is missing.
((name) => {'Hi ' + name})('Jess')

// returns: 'Hi Jess'
// explanation: explicit return in block exists
((name) => {return 'Hi ' + name})('Jess') 

// returns: undefined
// explanation: a block containing a single label. No explicit return.
// more: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label
((name) => {id: name})('Jess') 

// returns: {id: 'Jess'}
// explanation: implicit return of expression ( ) which evaluates to an object
((name) => ({id: name}))('Jess') 

// returns: {id: 'Jess'}
// explanation: explicit return inside block returns object
((name) => {return {id: name}})('Jess') 

我不理解那个语法...你是在使用类字面量创建一个类,然后用一个参数('Jess')调用隐式构造函数吗??我原以为你会这样做 ((name) => ({id: 'Jess'})) - Michael Dausmann
4
这是一个只有一个参数name的箭头函数,该函数用括号括起来,并使用一个参数“Jess”调用。每种情况下在=>)('Jess')之间的代码都是箭头函数的主体。可以将其视为形式为(function (name) { return { id: name } })('Jess')的立即执行函数表达式的简写形式。 - Russ Cam
确实非常有用!它可以帮助我们在使用箭头函数映射数组时发现Promises.all中的问题,并且您可以注意到如果没有为映射数组返回值,则会得到未定义数组。 - jay shah
让箭头函数的隐式返回成为系统性的,会有什么不利之处呢?就像Coffeescript一样...(虽然我不喜欢Coffeescript) - Augustin Riedinger
8
简而言之,由于 JS 解析器无法确定它期望的是表达式(例如包含对象字面量 {} 的表达式)还是块,因此它会假定 { } 表示一个块。这意味着当它看到 id: name 时,它认为 id: 是一个创建标签的表达式(JS 的一个很少使用的功能,涉及流程控制并使用:),然后在 id: 后面的 name 只是一个仅包含变量 name(不执行任何操作)的单独语句。 - iono
显示剩余2条评论

26

我理解这个经验法则...

对于那些实际上是转换(将参数进行一行操作)的函数,返回值是隐含的。

候选项为:

// square-root 
value => Math.sqrt(value)

// sum
(a,b) => a+b

对于其他需要使用代码块的操作(不只是一行代码), 必须显式地使用 return 语句。


12

这里还有另一个例子。

例如,在编写 React 中的功能组件时,您可以使用括号来包装隐式返回的 JSX。

const FunctionalComponent = () => (
  <div>
    <OtherComponent />
  </div>
);

19
你可以始终使用括号,这与JSX或React无关。 - Emile Bergeron

11

这是另一个让我感到困扰的案例。

// the "tricky" way
const wrap = (foo) => (bar) => {
  if (foo === 'foo') return foo + ' ' + bar;
  return 'nofoo ' + bar;
}

这里我们定义了一个返回匿名函数的函数。"棘手"的部分在于外部函数的函数体(以(bar) => ...开头的部分)在视觉上看起来像一个"块",但实际上不是。由于它不是块,隐式返回就会发生。

下面是wrap函数的执行过程:

// use wrap() to create a function withfoo()
const withfoo = wrap('foo');
// returns: foo bar
console.log(withfoo('bar'));

// use wrap() to create a function withoutfoo()
const withoutfoo = wrap('bar');
// returns: nofoo bar
console.log(withoutfoo('bar'));

我为了确保理解,将函数“取消箭头化”以进行解包。
这是第一个代码块的语义等效物,仅使wrap()函数体显式返回。此定义产生与上述相同的结果。这就是点的连接。将上面的第一个代码块与下面的代码块进行比较,很明显箭头函数本身被视为表达式而不是块,并具有隐含的返回值
// the explicit return way
const wrap = (foo) => {
  return (bar) => {
    if (foo === 'foo') return foo + ' ' + bar;
    return 'nofoo ' + bar;
  }
}

完全未箭化的wrap版本如下,虽然不像箭头加粗版那样紧凑,但更容易理解。
// the "no arrow functions" way
const wrap = function(foo) {
  return function(bar) {
    if (foo === 'foo') return foo + ' ' + bar;
    return 'nofoo ' + bar;
  };
};

最终,为了其他可能需要阅读我的代码的人和未来的我,我认为我更喜欢非箭头版本,可以在第一眼就被视觉理解,而箭头版本需要花费相当多的思考(以及在我这种情况下的实验)来理解。

很好的解释。你能表达一下这个方法/过程叫什么吗? - Mujibur
基本上,它就是这样做的对吧? const wrap = function(foo) { return function(bar) { if (foo === 'foo') return foo + ' ' + bar; return 'nofoo ' + bar; }; }; //运行wrap函数: wrap('foo')('bar'); - Mujibur

8
箭头函数允许你有一个隐式的返回值:不必使用 return 关键字就能返回值。
当函数体中有一条单行语句时它就会工作:

const myFunction = () => 'test'

console.log(myFunction()) //'test'

另一个例子是返回一个对象(记得用括号将花括号包裹起来,以避免被视为包装函数体的括号):

const myFunction = () => ({value: 'test'})

console.log(myFunction()) //{value: 'test'}


5
这应该是正确的答案,尽管需要更多的解释。基本上,当函数主体是一个表达式而不是一个代码块时,该表达式的值会被隐式地返回。如果我说错了,请纠正我。 - Paul-Sebastian Manole

1

如果符合以下条件,从箭头函数中省略大括号 {} 和 return 关键字是可以的: (1) 在 return 语句之前没有任何代码(例如赋值语句); (2) 返回的是单一实体 [注:单一实体可以是多行。如果是这样,那么你只需要使用普通的括号(),就像下面的例子一样:

posts.map(post => (
  <li key={post.id}>
    {post.title}
  </li>
))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接