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

Fix Object.assign example #4

Closed
connec opened this issue Jan 4, 2017 · 6 comments
Closed

Fix Object.assign example #4

connec opened this issue Jan 4, 2017 · 6 comments

Comments

@connec
Copy link
Contributor

connec commented Jan 4, 2017

The Object.assign example is currently incorrect.

function createMenu(config) {
  Object.assign(config, {
    title: 'Foo',
    body: 'Bar',
    buttonText: 'Baz',
    cancellable: true
  });
}

createMenu({ title: 'Not Foo' });

The title property will always be set to 'Foo'!

I was going to make a PR with a fix, but the approach really depends on whether the mutation of config is desirable.

How I would do it (this does not behave identically to the "bad" example):

function createMenu(config) {
  // makes a copy of `config`, with default values
  config = Object.assign({
    title: 'Foo',
    body: 'Bar',
    buttonText: 'Baz',
    cancellable: true
  }, config);
}

How you could do it with mutation (this is identical to the "bad" example):

function createMenu(config) {
  // mutates `config`, setting default values
  Object.assign(config, Object.assign({
    title: 'Foo',
    body: 'Bar',
    buttonText: 'Baz',
    cancellable: true
  }, config));
}
@halfzebra
Copy link

Sorry if I'm overthinking it, but I find it rather confusing to provide the example of object mutation in a procedural style, while advising to favor functional programming over imperative programming.

@rkichenama
Copy link

If the purpose is to mutate config to add defaults but keep changes, then the example should be

function createMenu(config) {
  Object.assign(
    config, // object to merge changes into
    {
      title: 'Foo',
      body: 'Bar',
      buttonText: 'Baz',
      cancellable: true
    }, // defaults
    config // overrides
);
}

createMenu({ title: 'Not Foo' });

IMHO, I think this is the case since there is no return and we are dealing with objects, passed by reference.

@kwelch
Copy link

kwelch commented Jan 5, 2017

I would say the best option would be to maintain the passed in parameter and create a new object all together that use defaults then user param.

function createMenu(options) {
  let config = Object.assign({}, {
      title: 'Foo',
      body: 'Bar',
      buttonText: 'Baz',
      cancellable: true
    }, // defaults
    options // overrides
  );
}

@rkichenama
Copy link

rkichenama commented Jan 5, 2017 via email

@connec
Copy link
Contributor Author

connec commented Jan 5, 2017

@rkichenama that example does not work because config has already mutated when the 'overrides' are applied:

let config = { key: 'override' }
Object.assign(config, { key: 'default' }, config)
console.log(config.key) // default

Hence the need for an additional Object.assign.

@kwelch that option is equivalent to the non-mutating version I specified - the defaults are already in a new object, so merging them into another new object is redundant.


Anyway, looks like this was fixed in d00ca4c with @kwelch's version.

@kwelch
Copy link

kwelch commented Jan 6, 2017

@connec I agree ours are the same, I just prefer not editing parameters if you are attempting to be functional.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants