2

In javascript, variables referring to objects are passed a "copy of the reference". I am struggling with this concept as it relates to merging two objects, and the effect on the references to those objects. Attempting to use underscore's extend, take the following (coffeescript) code:

a = {
    id: 1
    type: "cat"
    name: "Angry"
}
b = {
    id: 1
    type: "dog"
    owner: "Bill"
}

c = a
d = c
e = b


_.extend(a, b)

b = a

d.home = "Nashville"

console.log(a) //Object {id: 1, type: "dog", name: "Angry", owner: "Bill", home: "Nashville"} 
console.log(b) //Object {id: 1, type: "dog", name: "Angry", owner: "Bill", home: "Nashville"}
console.log(c) //Object {id: 1, type: "dog", name: "Angry", owner: "Bill", home: "Nashville"}
console.log(d) //Object {id: 1, type: "dog", name: "Angry", owner: "Bill", home: "Nashville"}
console.log(e) //Object {id: 1, type: "dog", owner: "Bill"}

As we can see, underscore did not 'merge' the objects. Instead, what has happened is that underscore set the attributes of the object referred to by b on the object referred to by a. Later, when we replace the reference held by b to point at the object referred to by a, e continues to hold a reference to the object originally referred to by b. This is because e was not assigned a reference to b, but rather a copy of the reference held by b. Similiarly, d holds a reference, not to c but to the object referred to by a.

I would like to find a way to truly merge the two objects, so that all references to both objects point at a single destination. Is this possible in Javascript, or am I precluded from doing this as a result of Javascript's object passing structure?

Community
  • 1
  • 1
Michael.Lumley
  • 2,345
  • 2
  • 31
  • 53
  • 1
    It's called `extend`, not `merge`… Have you read the docs? – Bergi Feb 26 '15 at 12:14
  • Sure, I did not expect extend to solve the problem, I intended it to demonstrate the problem. – Michael.Lumley Feb 26 '15 at 12:17
  • Do you know exactly what is you want? What happens is: both objects will stay in the memory. On top of that, the data contained in b will be copied to a. You can point a million variables at that object (a, b, c, d, ...), but the second object (originally made for b) stays in the memory too. – Emmanuel Delay Feb 26 '15 at 14:55

1 Answers1

3

I would like to find a way to truly merge the two objects, so that all references to both objects point at a single destination. Is this possible in Javascript, or am I precluded from doing this as a result of Javascript's object passing structure?

That's impossible without changing the references, i.e. having access to all the variables and re-assigning them with the new reference value - in your case, e = b just as you did b = a.

To get the expected result, you might want to do _.extend(a, b); _.extend(b, a); so that they have the same properties - however they stay two different objects.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • I was also thinking that `_.extend(a, b); _.extend(b, a);` should solve the problem. Even though they will stay different objects, their properties will be refering to same references. So kind of problem solved. Only care should be taken about overwriting of properties... – Vishwanath Feb 26 '15 at 12:22
  • I also considered extending in both directions, but ultimately I don't want to have to worry about keeping later attribute changes synced. – Michael.Lumley Feb 26 '15 at 13:00