简体   繁体   English

为什么我的箭头 function 返回“未定义”?

[英]Why is my arrow function returning `undefined`?

This question is intended as canonical duplicate target for questions about problems that stem from confusing the single-line/expression arrow function body syntax with automatic return with their multi-line/block version.此问题旨在作为规范重复目标,用于解决因混淆单行/表达式箭头 function 正文语法而产生的问题,并自动返回其多行/块版本。


I have an arrow function to add two numbers, but when I call it, it returns undefined .我有一个箭头 function 来添加两个数字,但是当我调用它时,它返回undefined Why?为什么?

const add = (a, b) => {
  a + b
}

console.log(add(1, 2)) // expected: 3, actually: undefined

Alternative question:替代问题:

My React component is supposed to render list items using map , but the list stays empty.我的 React 组件应该使用map呈现列表项,但列表保持为空。 Why?为什么?

<ul>
  {list.map(item => {
    <li>
      <a href="{item.url}">{item.name}</a>
    </li>
  }}
</ul>

Arrow functions support two different styles of bodies: expressions and blocks .箭头函数支持两种不同的 styles 体:表达式

If a single expression is provided (eg a + b ) without braces { } around it, that expression is automatically returned:如果提供了单个表达式(例如a + b )而周围没有大括号{ } ,则该表达式会自动返回:

const add = (a, b) => a + b

If a block enclosed by { } is provided, it works like a regular function body and requires a dedicated return statement to return a value:如果提供了一个由{ }括起来的块,它就像一个常规的 function 主体一样工作,并且需要一个专用的return语句来返回一个值:

const add = (a, b) => {
  return a + b
}

Single-expression bodies are often used to write simple functions in a concise way which execute one operation or condition, as in the following examples:单表达式主体通常用于以简洁的方式编写执行一个操作或条件的简单函数,如下例所示:

if (users.every(user => user.age >= 18)) { /* ... */ }

const emails = users.map(user => user.email)

const titleCased = string.replace(/\b\w/g, s => s.toUpperCase())

// in the following example, the return value is irrelevant
setTimeout(() => doStuff(1, 2, 3), 1000)

In most other cases, especially if you want to have multiple statements, loops or conditions in your function body, a block is used.在大多数其他情况下,特别是如果您想在 function 主体中包含多个语句、循环或条件,则使用块。

Note that you can have a function body spanning multiple lines even without a block if it is still a single expression, but if you would like to turn it into a block for readability reasons, you must not forget to add return (unless your function isn't supposed to return anything).请注意,如果 function 主体仍然是单个表达式,即使没有块,您也可以拥有跨越多行的主体,但是如果出于可读性原因,您想将其变成一个块,则一定不要忘记添加return (除非您的 function 是'不应该返回任何东西)。

Now, this is the reason why your add function is returning undefined - it neither has a single-expression body (the { } make it a block) nor does it have any return statement in its body.现在,这就是为什么您的add function 返回undefined的原因 - 它既没有单个表达式主体( { }使其成为块),也没有任何return语句在其主体中。 So, what happens is that a + b is evaluated, but the result isn't used for anything - it thrown away and execution continued, which then reaches the end of the function and returns without any return value since none was given, ie returning undefined .所以,发生的情况是a + b被评估,但结果不用于任何事情 - 它被丢弃并继续执行,然后到达 function 的末尾并返回没有任何返回值,因为没有给出任何返回值,即返回undefined


In the React case, the problem is the same.在 React 案例中,问题是一样的。 You are embedding the return value of a .map call, which should be an array of further content to render, but because your callback is not returning any value, you are mapping the items to several undefined values and rendering that at the end.您正在嵌入.map调用的返回值,该调用应该是要呈现的进一步内容的数组,但由于您的回调没有返回任何值,因此您将项目映射到几个undefined的值并在最后呈现

There is another twist here though: you may often need multiple lines in the element(s) that you return from a function like a map callback, but you will find that neither of the following two options looks quite clean:但是这里还有另一个转折:您可能经常需要在从 function 返回的元素中使用多行,例如map回调,但是您会发现以下两个选项看起来都不是很干净:

<ul>
  {list.map(item => <li>
    <a href="{item.url}">{item.name}</a>
  </li>}}
</ul>

<ul>
  {list.map(item => {
    return <li>
      <a href="{item.url}">{item.name}</a>
    </li>
  }}
</ul>

Instead, what is usually done is enclosing the expression in parentheses ( ) .相反,通常所做的是将表达式括在括号( ) It is a still a single expression at the end, avoiding the need for an extra return statement, but is a lot nicer to work with:最后它仍然是一个单一的表达式,避免了额外的return语句的需要,但使用起来要好得多:

<ul>
  {list.map(item => (
    <li>
      <a href="{item.url}">{item.name}</a>
    </li>
  )}
</ul>

For more information about arrow functions in general, see here .有关一般箭头函数的更多信息,请参见此处 To read about other differences between arrow functions and regular functions (such as different behavior of this ), see here .要了解箭头函数和常规函数之间的其他差异(例如this的不同行为),请参见此处

Arrow functions return code in these cases :箭头函数在这些情况下返回代码:

Case 1 : When it's written inline like below案例1 :当它像下面这样内联编写时

/* notice that this is an implicit return 
and we don't need a return statement here as the code is 
in the same line after the => */

const add = (a, b) => a + b  
    
console.log(add(1, 2)) // expected: 3

Case 2 : When it's written with round brackets () like this案例2 :当它用round brackets ()这样写时

Case 2 - example 1案例 2 - 示例 1

/* notice the round bracket here. 
You will use this when you have a 
block of code here unlike case 1 
where you had a single line to return */

const add = (a, b) => ( // this is round bracket, no return needed 
    a + b 
    // and other blocks of code. Look at the below JSX example for
    // for this case
)

console.log(add(1, 2)) // expected: 3

The above example is similar to first case 2 - example 1, but this case is more suitable for a single block of code mostly for JSX like below上面的示例类似于第一种情况 2 - 示例 1,但这种情况更适合单个代码块,主要用于 JSX,如下所示

Case 2 - example 2案例 2 - 示例 2

<ul>
  {list.map(item => ( // this is round bracket, no return needed
    <li>
      <a href="{item.url}">{item.name}</a>
    </li>
  )}
</ul>

Case 3 : With an explicit return statement when you use curly braces like this案例 3 :当您使用这样的花括号时,使用显式return语句

const add3 = (a, b) => { // curly braces + return statement
  return a + b;
};

const res3 = add3(1, 2);

console.log(res3); // 3

In your case, notice you're mixing both cases 2 and 3. Meaning, you are using curly braces as defined in case 3 and also not using return keyword then like in case 2 which is the reason it doesn't work.在您的情况下,请注意您将情况 2 和 3 混合在一起。意思是,您使用的是在情况 3 中定义的花括号,并且也没有像在情况 2 中那样使用 return 关键字,这是它不起作用的原因。

Code: https://codesandbox.io/s/javascript-forked-ckjg69?file=/src/index.js代码: https://codesandbox.io/s/javascript-forked-ckjg69?file=/src/index.js

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM