【问题标题】:Arrow function without curly braces没有花括号的箭头函数
【发布时间】:2022-01-19 06:03:21
【问题描述】:

我是 ES6 和 React 的新手,我不断看到箭头函数。为什么有些箭头函数在粗箭头之后使用花括号,有些使用括号? 例如:

const foo = (params) => (
    <span>
        <p>Content</p>
    </span>
);

对比

const handleBar = (e) => {
    e.preventDefault();
    dispatch('logout');
};

【问题讨论】:

标签: javascript reactjs ecmascript-6 arrow-functions


【解决方案1】:

括号返回单个值,花括号执行多行代码。

您的示例看起来令人困惑,因为它使用的 JSX 看起来像是多个“行”,但实际上只是被编译为单个“元素”。

这里有更多的例子,它们都做同样的事情:

const a = (who) => "hello " + who + "!";
const b = (who) => ("hello " + who + "!");
const c = (who) => (
  "hello " + who + "!"
);
const d = (who) => (
  "hello "
    + who
    + "!"
);
const e = (who) => {
  return "hello " + who + "!";
}; 

您还会经常看到对象字面量周围的括号,因为这是避免解析器将其视为代码块的一种方式:

const x = () => {} // Does nothing
const y = () => ({}) // returns an object

【讨论】:

  • 太棒了,谢谢。这也有助于我理解我遇到的其他一些错误。一旦可以,我会接受这是正确的。谢谢大卫
  • 人们也可以使用花括号来防止箭头函数返回一个值——或者使单行箭头函数不应该返回任何值。查看我的答案以获取示例(无法很好地将其格式化为评论)。
  • 我得到了 GrayedFox 的想法,但是,为什么有人甚至实现了这个?对我来说似乎有点棘手,因为在特殊情况下你不确定它应该是 () 还是 {}
  • 所以我只能在大括号中使用“return”而不是括号?如果是,为什么会这样?
  • @vikramvi 因为括号表示函数将返回其中单个语句的结果,即 const x = () => (x) 等于 const x = () => {return X} 。您始终可以使用花括号,但也可以使用括号来简洁地从单个语句中返回值。
【解决方案2】:

也可以使用花括号来防止单行箭头函数返回值——或者让下一个开发人员明白单行箭头函数在这种情况下不应该返回任何值。

例如:

const myFunc = (stuff) => { someArray.push(stuff) }
const otherFunc = (stuff) => someArray.push(stuff)

console.log(myFunc())    // --> logs undefined
console.log(otherFunc()) // --> logs result of push which is new array length

【讨论】:

    【解决方案3】:

    在您的第一个示例中,箭头函数的右侧显示了一个由分组运算符括起来的单个表达式:

    const foo = (params) => (
      <span>
        <p>Content</p>
      </span>
    );
    

    类似的可比案例如下:

    const foo = (params) => (<span><p>Content</p></span>);
    

    在上述使用单个表达式的情况下,区别在于右侧是函数的返回值

    另一方面,如果您使用花括号,JavaScript 会将其理解为声明:

    const foo = (params) => {} // this is not an object being returned, it's just an empty statement 
    

    因此,using 语句是一个很好的开始,您可以在其中包含多行代码,并且如果函数打算返回值,则需要使用“return”:

    const foo = (params) => {
        let value = 1; 
        return value;
    }
    

    如果你想以最短的形式返回一个空对象:

    const foo = (params) => ({}) 
    

    See tests

    【讨论】:

      【解决方案4】:

      实际上在一个公文包中,当有人在箭头函数声明中使用大括号时,它等于下面:

      const arrow = number => number + 1;
      
      |||
      
      const arrow = (number) => number + 1;
      
      |||    
      
      const arrow = (number) => ( number + 1 );
      
      |||
      
      const arrow = (number) => { return number + 1 };
      

      【讨论】:

      • 所以我只能在大括号中使用“return”而不是括号?如果是,为什么会这样?
      • @vikramvi,看,这只是一个简单的语法,当你的函数在执行上下文中没有任何内容时,只需用更少的代码让它变得简单,=&gt; 没有花括号意味着return ,简单易读,易于理解,包体积更小。看,那是纯粹的美。
      • 感谢您的信息,我明白了;但我的问题是;也可以将“return”与 ( ) 一起使用?
      • @vikramvi,显然没有。
      【解决方案5】:

      括号用于箭头函数返回一个对象。

      () => ({ name: 'YourName' })  // This will return an object
      

      相当于

      () => {
         return { name : 'YourName' }
      }
      

      【讨论】:

        【解决方案6】:

        回复重复帖(question posted here),仅供参考:

          var func = x => x * x;                  
            // concise body syntax, implied "return"
        
            var func = (x, y) => { return x + y; }; 
            // with block body, explicit "return" needed
        

        供参考:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#Function_body

        另请注意: 如果您从胖箭头函数返回一个对象字面量,那么您必须将该对象括在括号中,例如,myFunc = () =&gt; ({ data: "hello"})。如果省略括号,则会收到错误消息,因为构建工具会假定对象字面量的花括号是函数体的开始和结束。

        【讨论】:

          【解决方案7】:

          括号有一个隐式的return语句,而花括号你需要一个显式的return语句

          【讨论】:

            【解决方案8】:

            如果你在箭头后面使用花括号来定义函数体,你必须使用'return'关键字来返回一些东西。

            例如:

            const myFun1 = (x) => {
                return x;
            }; // It will return x
            
            const myFun2 = (x) => {
                x;
            }; // It will return nothing
            

            如果使用括号,则无需提及'return'关键字。

            例如:

            const myFunc1 = (x) => x; // It will return x
            
            const myFunc2 = (x) => (x); // It will also return x
            

            【讨论】:

              【解决方案9】:

              每个功能都有两个方面。

              首先是每个函数,不仅仅是箭头函数,都有一个执行上下文(一个块作用域),在其中创建和使用变量。

              换句话说,在函数的大括号 { ... } 内,在那里声明和分配的内容保留在那里,并且对外部函数/或变量不可见。

              例如,当写一些东西时

              let x = 100;
              
              function doSomething() {
                let x = 50;
                console.log(x);
              }
              
              doSomething();     // 50
              console.log(x);    // 100
              

              这两个值都显示在控制台中(而不是“外部的 x 被函数内部的 x 替换”)。

              您会看到,尽管 let 通常不允许再次声明其他变量 x(具有相同的名称 x),在这种情况下,因为第二个 x 是在 { ... } 内声明和初始化的,所以它不会改变外面的 x,这也是因为在函数 doSomething 被调用之后,其中的 x 被创建、分配、打印在控制台中,然后被销毁(从内存中删除)。因此,每次我们通过运行 doSomething() 调用该函数时都会发生该过程。

              所以这是理解函数时要考虑的第一个方面:它们执行然后忘记由花括号内的代码创建的值。

              正因为如此,它们的第二个方面更容易理解——因为函数不能独立于其他函数工作,它们还需要向其他函数发送数据,因此它们有一些“报告方面”用于外部化某些部分结果计算在花括号内,这正是 return 语句存在的原因。

              Return存在于每个函数中,甚至在console.log或alert()中,甚至在doSomething()中,但是在这些我们没有明确说明的情况下为它设置一些东西,它总是'return undefined'。

              因此没有必要编写它,而是知道在您不返回特定内容的地方,函数本身会通过返回 undefined 来为您完成。

              当你编写(或使用)一个函数只是为了执行某事时,它也会返回 undefined。总是。

              您可以使用(显然)没有声明返回的每个函数检查该内容:

              let x = alert(100);
              console.log(x); // undefined
              
              let y = doSomething(); // console prints 50
              console.log(y);        // 50, then undefined --- 2 lines
              
              console.log(alert('Hello')); // undefined
              
              console.log(console.log('Okay')); // Okay , then undefined
              

              这是为什么呢?

              因为 alert() 是全局对象 window (在浏览器中)的一种方法(所以它实际上是 window.alert() )和 console.log() (与 window.console.log() 相同) ,同样),执行某些操作(在警告框或控制台中打印任何介于 () AND THEN return undefined 之间的内容)。

              现在,回到箭头函数,它们不仅是编写函数的一种新的符号方式,而且还具有一些特定的功能。

              首先,如果箭头函数的()之间只有一个参数,可以不用括号写出来。

              其次,如果花括号内只有一条语句,您也可以省略花括号。

              第三个,如果单条语句是return语句,可以省略return这个词。

              不知何故,如果需要,使用这些我们可以将许多常用函数转换为箭头函数:

              function doSomething() {let x = 50; console.log(x);} // as function declaration
              
              let doSomething = function() {let x = 50; console.log(x);}; // as function expression, which is an anonymous function assigned to the variable 'doSomething'
              
              let doSomething = () => {let x = 50; console.log(x);}; // as arrow function
              
              // let's transform it further
              
              let doSomething = () => {console.log(50)}; //
              
              // that is equivalent to ---- let doSomething = () => {console.log(50); return undefined};
              // or even to           ---- let doSomething = () => {return ( console.log(50) ) };
              // because anyways, *console.log* has *return undefined* in it, as explained above
              
              //which is the same as  ---- let doSomething = () => {return console.log(50) };
              
              // let's now apply the rules 2 and 3 from above, one by one:
              
              let doSomething = () => return console.log(50);
              
              let doSomething = () => console.log(50);
              
              // Obviously, this just shows how we could rewrite many usual functions (functions declarations) into arrow functions
              // we can do that safely if we don't have any **this** involved in the functions, of course
              // also, from all lines of code above only one must remain, for example the last one.
              
              // the last one, despite only having ---- console.log(50) --- as the execution aspect, it also ---- returns undefined ---- as well
              
              // obviously ---- console.log( typeof doSomething );   // function
              // while     ---- console.log( typeof doSomething() ); // undefined
              

              如果一个箭头函数有 2 个或更多参数,我们不能省略它们周围的括号:

              function sum(a, b) {let total = a + b; return total}
              
              let sum = function(a, b) {let total = a + b; return total};
              // or
              let sum = (a, b) => {let total = a + b; return total};
              // or
              let sum = (a, b) => {return a + b};
              // or
              let sum = (a, b) => a + b;
              

              对于上面的简单操作,粗箭头符号'=>'可以被“读取”,因为被转换为,换句话说,a和b 被(被)转化为 a + b。

              与此相反,还有一些函数可以验证一些数据(例如检查数据类型等),比如这个

              let isNumber = x => typeof x === "number";
              // or
              let isNumber = (x) => {return (typeof x === "number")};
              // obviously, 
              isNumber("Hello, John!"); // false
              

              那些不转换数据,因此箭头符号可以被解读为条件为或类似。

              换句话说,像这样的函数

              let double = x => x * 2    // 'double' is a function that transforms x into x*2
              

              与检查不一样(主要用于过滤器、排序和其他类型的验证函数,通常作为回调函数等)

              let isArray = arr => Array.isArray(arr) // that last one already returns boolean by itself, no need to write return (Array.isArray() etc)
              

              关于return的最后一件事是,当您编写多行代码时,ASI(自动分号插入)将插入一个';'如果你在写完返回字后误按了回车,就会破坏代码,因此而不是

              return
              a+b;
              

              您的代码将表现为

              return;
              a+b;
              

              所以你最好用括号写代码:

              return (
                a + b
              );
              

              正如 MDN 网站 here 中所解释的那样。

              【讨论】:

                猜你喜欢
                • 2017-05-22
                • 2016-05-28
                • 2020-06-21
                • 1970-01-01
                • 2018-04-25
                • 2020-11-13
                • 2019-06-18
                • 2020-03-01
                相关资源
                最近更新 更多