Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Object.assign instead of manipulating input objects #98

Closed
SamVerschueren opened this issue Jul 8, 2017 · 7 comments
Closed

Object.assign instead of manipulating input objects #98

SamVerschueren opened this issue Jul 8, 2017 · 7 comments

Comments

@SamVerschueren
Copy link
Contributor

I myself did it wrong in the early days, and I definitely come across this issue quite a lot.

module.exports = opts => {
    opts.foo = opts.foo || 'bar';
};

While it should've been

module.exports = opts => {
    opts = Object.assign({
        foo: 'bar'
    }, opts);
};

Not sure how easy it would be to detect this though.

@sindresorhus
Copy link
Owner

Slightly relevant issue: https://github.com/sindresorhus/eslint-config-xo/issues/18

@sindresorhus
Copy link
Owner

sindresorhus commented Jul 8, 2017

Seems like it should be possible to detect the arguments and to find the cases where something is assigning to properties of those arguments. Could maybe use code path analysis.

Should use object spread and not Object.assign().

@MrHen
Copy link
Contributor

MrHen commented Aug 19, 2018

Seems like the better fix is to make sure that objects in parameters are treated as immutable. The implementation for immutable/no-mutation might work as a starting point.

// objects
function foo(bar) {
    delete bar.zaz; // fail
    bar.zaz = bar.zaz || 'zaz'; // fail
    bar = {
        zaz: 'zaz',
        ...bar
    }; // pass
}

// arrays
function foo(bar) {
    bar.push('zaz'); // fail
    bar.pop() // fail
    bar.unshift('zaz'); // fail
    bar.shift(); // fail
    bar.length = 0; // fail
    delete bar[0]; // fail
    bar = {
        ...bar,
        'zaz'
    }; // pass
}

I'd argue that overshadowing parameter is also bad but should be a different rule.

@MrHen
Copy link
Contributor

MrHen commented Aug 29, 2018

Turns out what I was mentioning is already a rule: https://eslint.org/docs/rules/no-param-reassign

There is also a functional difference between foo || bar and Object.assign. If you set a property to null and want a default then you can use || but not Object.assign.

@sindresorhus
Copy link
Owner

There is also a functional difference between foo || bar and Object.assign. If you set a property to null and want a default then you can use || but not Object.assign.

I've been using Object.assign for options arguments for years and that has never been a problem in practice.

@MrHen
Copy link
Contributor

MrHen commented Aug 30, 2018

It's not really a problem. It's just a slight functional difference. In my opinion, I think the Object.assign pattern is more clear / less surprising anyway.

In any case, I was just pondering whether I wanted to help out with this feature -- but I'd rather have immutable parameters and/or use destructuring directly in the function signature. I'll go dig up something else to poke at.

@fregante
Copy link
Collaborator

fregante commented Oct 1, 2020

Duplicate of #29

It's being fixed #632, but using default parameters instead of Object.assign

@fregante fregante marked this as a duplicate of #29 Oct 1, 2020
@fregante fregante closed this as completed Oct 1, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants