-2

I have objects A and B and would like pass properties of A into B by reference, without passing B's props into A. I.e.:

const A = { d: 1, e: 2 };
const B = { f: 10, g: 20 };
const C = Object.assign(A, B);

A.d = 10;

console.log(C); // { d: 10, e: 2, f: 10, g: 20} as desired
console.log(A); // { d: 10, e: 2, f: 10, g: 20} but would like just { d: 10, e: 2 }

Is there a way to do this, without using functions/getters to copy things?

Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
Adam B.
  • 788
  • 5
  • 14
  • Do you want to allow setting values in `C`? – Unmitigated Apr 14 '23 at 21:43
  • Does this answer your question? [How can I merge properties of two JavaScript objects dynamically?](https://stackoverflow.com/questions/171251/how-can-i-merge-properties-of-two-javascript-objects-dynamically) – tevemadar Apr 14 '23 at 22:02
  • Notice that `C === A` because that's how `Object.assign` works. If you want a separate copy, create a new object, with `C = Object.assign({}, A, B)` or `C = {...A, ...B}`. – Bergi Apr 14 '23 at 22:10
  • 2
    *'without using functions/getters to copy things'* no, primitive values are not copied by reference so you need an active method of propagating the change. If you set the values as objects then yes. Also if you want the properties of`A` in `B` then you should reverse the order you are passing them to `Object.assign`. – pilchard Apr 14 '23 at 22:10
  • Right, thanks, that makes sense, `Object.assign()` returns reference to the original (modified) object but the primitive properties are not copied by reference, the object is. – Adam B. Apr 14 '23 at 22:16

3 Answers3

2

You could use a Proxy to create a view over the objects A and B.

const A = { d: 1, e: 2 };
const B = { f: 10, g: 20 };
const C = new Proxy({}, {
  get(target, prop, receiver) {
    return Object.hasOwn(B, prop) ? B[prop] : A[prop];
  },
  ownKeys() {
    return [...new Set(Object.keys(A).concat(Object.keys(B)))];
  },
  getOwnPropertyDescriptor(target, prop) {
    return Object.getOwnPropertyDescriptor(Object.hasOwn(B, prop) ? B : A, prop);
  }
});

A.d = 10;

console.log(Object.fromEntries(Object.entries(C))); // { d: 10, e: 2, f: 10, g: 20}
console.log(A); // { d: 10, e: 2 }
Unmitigated
  • 76,500
  • 11
  • 62
  • 80
0

You could take an empty object as target. This does not mutate given objects.

const
    a = { d: 1, e: 2 },
    b = { f: 10, g: 20 },
    c = Object.assign({}, a, b);

a.d = 10;

console.log(c); // { d: 10, e: 2, f: 10, g: 20 }
console.log(a); // { d: 10, e: 2 }
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • 3
    I don't know why you rate this answer when it's wrong. c will be "{ d: 1, e: 2, f: 10, g: 20 }" and won't get d value updated when doing a.d = 10 – Anton Honcharuk Apr 14 '23 at 21:54
  • @AntonHoncharuk, `a` is changing, `c` is not. what else do you get? – Nina Scholz Apr 14 '23 at 21:56
  • 1
    The expected output for `c` is `{ d: 10, e: 2, f: 10, g: 20 }`, but your code outputs `d: 1`. – Unmitigated Apr 14 '23 at 22:01
  • @all, right, i see it as error of op. this approach takes two objects and merge this and does not change the source objects. `a.c` changes only `a`. – Nina Scholz Apr 14 '23 at 22:04
  • Yeah, this doesn't really work for me, I don't want to copy the properties but instead have a pointer to the properties of the source object, without adding target object's properties to the source. – Adam B. Apr 14 '23 at 22:05
  • what does it look like? – Nina Scholz Apr 14 '23 at 22:06
-1

Yes, you can use the spread operator to copy the properties of object A into a new object, and then use Object.assign to merge that new object with object B. This will create a new object with the properties of A and B, without modifying either of the original objects. Here's an example:

const A = { d: 1, e: 2 };
const B = { f: 10, g: 20 };
const C = Object.assign({...A}, B);

A.d = 10;

console.log(C); // { d: 1, e: 2, f: 10, g: 20} as desired
console.log(A); // { d: 10, e: 2 } as desired