1

So I want to prevent overriding shared keys, when doing a mixin with JS, so we have:

const v = {
  a: {
    b: {
      c: 4,
      d: 'str'
    }
  }
};


console.log(Object.assign({}, v, {a: {b: {c: 5}}}));

this will log:

{ a: { b: { c: 5 } } }

but I am looking for this instead:

{ a: { b: { c: 5, d: 'str' } } }

anyone know how to do this (preferably without a library).

  • 1
    I was responding when it was marked duplicate :'( Try this: `const a = {}; const object3 = {...a, ...v }` – Katie Jun 24 '19 at 23:08
  • 1
    This is a duplicate but I think this is more appropriate https://stackoverflow.com/questions/27936772/how-to-deep-merge-instead-of-shallow-merge – doublesharp Jun 24 '19 at 23:08
  • FWIW you are trying to deep merge instead of shallow merge. – doublesharp Jun 24 '19 at 23:09
  • 1
    Not sure I agree with the dupe, I'd say it's more [How to deep merge instead of shallow](https://stackoverflow.com/questions/27936772/how-to-deep-merge-instead-of-shallow-merge) – James Jun 24 '19 at 23:10
  • Agreed, I could not find that one (SO really needs to improve search) – Jonas Wilms Jun 24 '19 at 23:12
  • @katie um ... not sure how that is different from the code in the question. – Jonas Wilms Jun 24 '19 at 23:13
  • FWIW it depends really on what you value - brevity or nativeness, this can obviously be written without the use of a 3rd party library, but then a 3rd party library would allow you to write more succinct code e.g. [lodash.merge](https://lodash.com/docs/4.17.11#merge) supports deep merging. – James Jun 24 '19 at 23:13
  • Hey @JonasWilms ! The `...` will fill in all the missing attributes, so it's not a shallow copy but a deep copy. – Katie Jun 24 '19 at 23:54
  • 1
    @Katie I don't think the spread technique works, it seems to work the same way Object.assign works. –  Jun 25 '19 at 00:23
  • @Katie see: https://gist.github.com/ORESoftware/d83682d73433c79ac2c69339e3672182 –  Jun 25 '19 at 00:27
  • @MrCholo I think I'm confused about the question... the spread technique gets you the result you're looking for ( `{ a: { b: { c: 5, d: 'str' } } }` ) as seen in the gist you made: https://gist.github.com/ORESoftware/d83682d73433c79ac2c69339e3672182 Is there more to this question that I've missed? – Katie Jun 25 '19 at 18:04
  • last time I checked it gives me: `{ a: { b: { c: 4, d: 'str' } } }`, so 4 not 5, that's the problem –  Jun 25 '19 at 18:31

1 Answers1

0

A fairly naïve solution which cannot handle cycles:

const mixin = (a, b) => {

  for (let [key, val] of Object.entries(b)) {

    if (typeof val !== 'object') {
      a[key] = b[key];
      continue;
    }

    if (val === null) {
      a[key] = b[key];
      continue;
    }

    if (!a.hasOwnProperty(key)) {
      a[key] = b[key];
      continue;
    }

    mixin(a[key], b[key]);
  }

  return a;

};

const mixinInclusive = (...v) => {
  return v.reduce(mixin, {});
};


console.log(mixinInclusive(v, {a: {b: {c: 5}}}));