I came across this short snippet (HERE)
const pick = (obj, arr) =>
arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {});
And I don't understand the role of parentheses in this part
(curr in obj && (acc[curr] = obj[curr]), acc)
() => (... && (... = ...), ...)
// First, parentheses after the arrow function means we are returning what is inside
() => (...)
// This looks like a short if statement
curr in obj && ...
// Why are we grouping the assignment into parentheses here?
(acc[curr] = obj[curr])
// What does (..., ...) is supposed to to
() => (... && (...), acc)
The parentheses are required because otherwise, this expression:
curr in obj && acc[curr] = obj[curr]
would be invalid syntax, because the left-hand side of the = would evaluate to curr in obj && acc[curr] (an expression), not a reference that can be assigned to.
But this is horrible code - it's quite confusing. A much better version would be
const pick = (obj, arr) => {
const output = {};
for (const curr of arr) {
if (curr in obj) {
output[curr] = obj[curr]
}
}
return output;
};
That's so much easier to understand at a glance, isn't it?
Another option is to filter the entries of the object:
const pick = (obj, arr) => Object.fromEntries(
Object.entries(obj)
.filter(([key]) => arr.includes(key))
);
This:
(curr in obj && (acc[curr] = obj[curr]), acc)
is another way of writing the following:
if (curr in obj) {
acc[curr] = obj[curr];
}
return acc;
Not only the one-liner is less readable, it can also be considered as abusing the comma operator.
Code readability is more important than writing less lines of code.
// What does (..., ...) is supposed to do
() => (... && (...), acc)
Parenthesis in the following expression:
(curr in obj && (acc[curr] = obj[curr]), acc)
ensure that:
Overall expression is evaluated as a single expression that consists of multiple sub-expressions
Assignment is evaluated without the curr in obj && part because without those parenthesis, curr in obj && acc[curr] = obj[curr] is invalid syntax.
With parenthesis, the expression:
(acc[curr] = obj[curr])
will evaluate to the value of obj[curr]. So the expression:
curr in obj && (acc[curr] = obj[curr])
will become:
curr in obj && <assignment value>