no-param-reassign with props, again
See original GitHub issueHello!
A comment regarding this change: #626 #627
While I agree in general that function parameters should not be mutated, this change gave me a lot of errors in code that I consider as safe. For example:
['foo', 'bar', 'qux', 'foo'].reduce((accumulator, value) => {
accumulator[`_${value}`] = true;
return accumulator;
}, {});
I know, I can change this rule in my .eslintrc
or for this particular line of code. But this reduce
pattern is quite common in JavaScript. Lodash has also a bunch of functions that work this way. There’s little risk mutating the accumulator since the reduce operation as a whole is non-mutating.
While the { "props": true }
rule might catch some errors, it mostly produces false positives in my codebases. I’m already writing in a non-mutating, mostly pure functional style.
Related, the example in https://github.com/airbnb/javascript#7.12 isn’t helpful IMHO. The “good” and “bad” examples do not seem to match. The “bad” example mutates an object. The “good” example illustrates input normalization. Which is a different thing IMHO. 😉
Perhaps there are cases where people accidentally mutate parameters just to normalize input. Then a better example would be:
// bad
function f1(obj) {
obj.key = obj.key || 1; // Mutate to normalize
// Use obj.key
}
// good
function f2(obj) {
const key = obj.key || 1; // Normalize without mutating
// Use key
}
But I think people are mutating parameters not just accidentally, but more commonly to make changes on objects. For example:
function doSomethingWithObject(obj) {
obj.hello = 'world';
obj.list.sort();
delete obj.foo;
}
Then, a good alternative would be a pure function. It could clone the input, then augment it. Or use a library for immutable data that has smart lists and hashes, like Immutable.js.
Assuming this case, a better example would be:
// bad
function f1(obj) {
obj.key = 1;
}
// good
function f2(obj) {
return Object.assign({}, obj, { key: 1 }); // Shallow clone
}
Or with prototypal delegation:
function f2(obj) {
const obj2 = Object.create(obj);
obj2.key = 1;
return obj2;
}
(Or with a library like Immutable.js…)
I think the bottom line is that the topic of immutability is too complex to be covered in a simple example. And the rule no-param-reassign: [2, { "props": true }]
cannot cover the nuances here. I propose to reconsider the switch to { "props": true }
.
Issue Analytics
- State:
- Created 8 years ago
- Reactions:20
- Comments:38
Top GitHub Comments
You’re right, my mistake. I’ve updated my original comment.
Performance is the last and least important concern when programming - it’s easy to speed up clean code, but it’s hard to clean up fast code.
This is a rule we use at Airbnb - in the reducer case, if the body of your reducer is
return Object.assign({}, accumulator, { [key]: value })
then you’ll avoid mutation as well as satisfy the linter (both in spirit and in fact).Mutation should be avoided in all its forms, and our style guide tries to be consistent with this belief.