Javascript 在没有花括号的箭头函数中使用多个表达式的做法是什么

Javascript 在没有花括号的箭头函数中使用多个表达式的做法是什么,javascript,ecmascript-6,functional-programming,Javascript,Ecmascript 6,Functional Programming,我喜欢探索JavaScript的局限性,并想知道是否可以使用箭头函数,其中最后一个表达式是return语句 幸运的是,这是可能的,但是在同一范围内设置变量有一些缺点 [1,2,3,4,5].reduce((sum, element) => (const doubleSum=sum+sum, doubleSum+element)); 返回未识别的标识符(指doubleSum) 解决办法是这样写 let doubleSum; [1,2,3,4,5].reduce((sum, element

我喜欢探索JavaScript的局限性,并想知道是否可以使用箭头函数,其中最后一个表达式是return语句

幸运的是,这是可能的,但是在同一范围内设置变量有一些缺点

[1,2,3,4,5].reduce((sum, element) => (const doubleSum=sum+sum, doubleSum+element));
返回未识别的标识符(指doubleSum)

解决办法是这样写

let doubleSum; 
[1,2,3,4,5].reduce((sum, element) => (doubleSum=sum+sum, doubleSum+element));
现在没有卷曲背景,我可以通过函数中的两个表达式得到
sum+sum+元素的和。这不是一个很好的示例用法,但它展示了如何使用没有花括号的2个表达式

这样做的结果将是
57
,因为每次迭代只返回
doubleSum+元素
。如果您想将其拆分为更可读的部分,那么这将非常适合于计算

另一个例子是记录每次迭代的结果,而不必使用花括号

[1,2,3,4,5].reduce((sum, element) => (console.log(sum), sum+sum+element));
//1
//4
//11
//26
//57
我真的很喜欢这种语法,但我不知道这是否是一种不好的做法,因为上面没有提到它

我不知道这是不是一种坏习惯

是的,在数组函数的作用域之外声明
doubleSum
显然是一种不好的做法。不要那样做

另一个例子是使用不带花括号的
console.log
。我非常喜欢这种语法,但在Arrow函数中没有提到


是的,这是因为它不是特定于箭头函数的。你只是在这里使用和。在there中可以找到一些类似的用法。

我认为您试图实现的可能会使代码难以阅读。使用带箭头函数的大括号并没有错。如果要保持reduce回调干净,可能需要执行以下操作:

const doubleSumAndAddElement = (sum, element) => {
    console.log(sum);
    return 2 * sum + element;
}

[1,2,3,4,5].reduce(doubleSumAndAddElement);

不能在表达式中声明变量。但是你可以建立一个函数表达式并直接调用它(称为IIFE),这样你就得到了局部参数:

 [1, 2, 3, 4].reduce((sum, value) => (double => double + value)(sum + sum));

如果这是有用的,那是另一回事。

你所说的
就是逗号运算符()

这个操作符来自C语言,在C语言中,用例通常是多个变量(
vari,j,k
)和特定宏(这是一个难题)的单行声明

大多数现代语言都放弃了这个操作符,转而支持更高的抽象

但即使我们跳过了历史,我也会认为最佳实践的主要目标之一是可读性。这绝对不是为了省去几次击键

现在比较一下:

let doubleSum; 
[1,2,3,4,5].reduce((sum, element) => (doubleSum=sum+sum, doubleSum+element));

其中一个示例将
doubleSum
声明为用于所有
reduce
迭代的闭合变量,而另一个示例将
doubleSum
声明为每个迭代的局部变量。你认为哪一个更能表达你的意图?哪一个更容易重构而不必担心打破某些奇怪的情况

对于日志记录示例,这一点并不清楚。但是,通常认为将每个副作用(如记录消息)放在单独的语句中(以
结尾的行)是一种好的做法

想象一下:

someArray.map((element) => (console.log(element), doSomething(element)));
然而,由于某些原因,
doSomething
并没有按照您预期的方式工作。让我们添加一些日志记录:

let intermediate;
someArray.map((element) => (
    console.log(element),
    intermediate = doSometing(element),
    console.log(intermediate),
    intermediate));
我们又回到了
intermediate
的奇怪范围问题上。这种更改甚至可能不是那么容易做到-您希望在
map
回调中执行某些操作,但实际上您必须在其范围之外创建一个变量才能执行此操作。现在想象一下,映射回调的复杂性将增加到有几个这样的绑定变量。或者可能会有带有更多变量的if/else分支。然后,您可能希望将其提取到一个单独的函数中:现在您需要再次对所有绑定变量进行推理

用积木怎么样

someArray.map((element) =>
{
    console.log(element);
    doSomething(element);
});
变成

someArray.map((element) =>
{
    console.log(element);
    const intermediate = doSometing(element);
    console.log(intermediate);
    return intermediate;
});

现在,除了映射回调的内部块之外,我们不需要编辑任何其他内容-更改更容易执行和解释。引入更多变量?没问题,他们都在回叫室。将回调提取为单独的函数?也没问题。这段代码的意图很清楚。

“这会返回未识别的标识符”-我得到了
意外的令牌常量。这显然是一个语法错误,不是吗?是的,我也做了这个解决方案
[1,2,3,4,5].reduce((sum,element)=>element+(currentSum=>currentSum+currentSum)(sum))
这似乎是最明智的解决方案,可能应该提到逗号分隔,因为如果没有分组语法,您的示例将无法编译。对我来说,这是非常可读的。不过,我确实觉得
中级
的范围界定是一个问题,从我的角度来看,这似乎是一种不好的做法reading@Pavlo感谢您的反馈,我已经扩展了答案并修复了代码示例。
someArray.map((element) =>
{
    console.log(element);
    const intermediate = doSometing(element);
    console.log(intermediate);
    return intermediate;
});