javascript - ES6 中的 Array.reduce(),隐式返回和语法糖。到底发生了什么?
问题描述
我有兴趣了解这个算法内部发生了什么。让我们考虑以下数据集:
const data = [
{
emp_code: "a001",
company_code: "company_a",
name: "abx",
details: [],
details_dtypes: []
},
{
emp_code: "b002",
company_code: "company_b",
name: "xbz ",
details: [],
details_dtypes: []
},
{
emp_code: "a002",
company_code: "company_a",
name: "xbz ",
details: [],
details_dtypes: []
},
{
emp_code: "b003",
company_code: "company_b",
name: "xbz ",
details: [],
details_dtypes: []
}
];
现在,如果我想将这些数据压缩到一个object {}
,其中每个键都是唯一的company_code
,并且其对应的值是array []
该emp_codes
公司的一个,我可以执行以下操作:
let result = data.reduce((r, c) => {
r[c.company_code] = [...(r[c.company_code] || []), c.emp_code];
return r;
}, {});
在上面,我们显式地返回了最终的对象,这看起来很清楚。
现在,我最近发现你可以用一些语法糖来缩短它,如下所示:
let result = data.reduce(
(r, c) =>
(r[c.company_code] = [...(r[c.company_code] || []), c.emp_code]) && r,
{}
);
结果是相同的,但我不确定这怎么可能。我的理解reduce()
是有一个内部循环遍历每个项目并允许您应用某些逻辑来制定最终结果。我看到他们正在使用&&
操作员。我的假设是括号之间的逻辑()
像传统reduce()
方法一样执行,完成后,我们只需返回结果,因此&& r
.
但这似乎是错误的。内循环还在发生吗?如果是他们如何能够在第一次迭代后不简单地执行条件而将其隔离,因此通过返回r
. r
他们是否在循环的每次迭代中返回?
这是一个沙盒,显示两种算法都在工作:https ://codesandbox.io/s/hooks-with-reduce-nested-data-goee1 。非常感谢您的贡献:)
解决方案
对于&&
,如果涉及的所有表达式都是真值,则它的计算结果为最终表达式的值 - 之后的表达式&&
。所以,如果你有这样的代码:
function foo() {
<some expression>;
return bar;
}
你也可以这样写
function foo() {
return <some expression> && bar;
}
或者,使用箭头函数的隐式返回:
const foo = () => <some expression> && bar;
这相当于
const foo = () => {
<some expression>;
return bar;
};
所以是的,对于您的代码,&& r
在箭头函数的末尾,这意味着r
在每次迭代时都会隐式返回。
综上所述,这与语法糖几乎相反。如果您通过minifier运行代码,您经常会看到这种情况,其目标是尽可能减少 Javascript 中的文本量。但是缩小的代码通常很难阅读,正如您的问题所示,这也不例外。如果使用隐式return
需要逗号操作符或利用&&
来评估布尔值以外的东西,则代码可能太混乱而难以阅读,而显式return
可能是更好的选择。
您还可以考虑推送到累加器对象中的现有数组,从而避免创建许多不必要的中间数组,这些中间数组只会在以后传播:
let result = data.reduce((r, c) => {
if (!r[c.company_code]) {
r[c.company_code] = [];
}
r[c.company_code].push(c.emp_code);
return r;
}, {});
那是我更喜欢的代码。它有点长,但是当每个语句/逻辑分支都在自己的行上时,它更容易阅读。
推荐阅读
- chart.js - ChartJS 甜甜圈图,但带有勾号
- java - 如何避免 Junit 中的 UnsupportedEncodingException
- javascript - Node API - 在处理任何请求之前执行 GET 请求
- ios - 隐藏动态框架的符号化崩溃日志
- scala - 在 SBT 项目中使用空手道
- java - 如何在 Spring-boot REST 上使用 Jackson 更改响应结构
- javascript - Ionic 3 - 平移事件在手机上缺少“目标”
- python-3.x - 带有分页的 Sqlalchemy union_all 无法正常工作
- java - 如何查找我的对象是否扩展了给定的抽象类?
- android - 清除 Firebase 本地写入队列尚未手动同步