# Object copying, references One of the fundamental differences of objects vs primitives is that they are stored and copied "by reference". Primitive values: strings, numbers, booleans -- are assigned/copied "as a whole value". For instance: ```js let message = "Hello!"; let phrase = message; ``` As a result we have two independent variables, each one is storing the string `"Hello!"`. ![](variable-copy-value.svg) Objects are not like that. **A variable stores not the object itself, but its "address in memory", in other words "a reference" to it.** Here's the picture for the object: ```js let user = { name: "John" }; ``` ![](variable-contains-reference.svg) Here, the object is stored somewhere in memory. And the variable `user` has a "reference" to it. **When an object variable is copied -- the reference is copied, the object is not duplicated.** For instance: ```js no-beautify let user = { name: "John" }; let admin = user; // copy the reference ``` Now we have two variables, each one with the reference to the same object: ![](variable-copy-reference.svg) We can use any variable to access the object and modify its contents: ```js run let user = { name: 'John' }; let admin = user; *!* admin.name = 'Pete'; // changed by the "admin" reference */!* alert(*!*user.name*/!*); // 'Pete', changes are seen from the "user" reference ``` The example above demonstrates that there is only one object. As if we had a cabinet with two keys and used one of them (`admin`) to get into it. Then, if we later use another key (`user`) we can see changes. ## Comparison by reference The equality `==` and strict equality `===` operators for objects work exactly the same. **Two objects are equal only if they are the same object.** Here two variables reference the same object, thus they are equal: ```js run let a = {}; let b = a; // copy the reference alert( a == b ); // true, both variables reference the same object alert( a === b ); // true ``` And here two independent objects are not equal, even though both are empty: ```js run let a = {}; let b = {}; // two independent objects alert( a == b ); // false ``` For comparisons like `obj1 > obj2` or for a comparison against a primitive `obj == 5`, objects are converted to primitives. We'll study how object conversions work very soon, but to tell the truth, such comparisons occur very rarely, usually as a result of a coding mistake. ## Cloning and merging, Object.assign So, copying an object variable creates one more reference to the same object. But what if we need to duplicate an object? Create an independent copy, a clone? That's also doable, but a little bit more difficult, because there's no built-in method for that in JavaScript. Actually, that's rarely needed. Copying by reference is good most of the time. But if we really want that, then we need to create a new object and replicate the structure of the existing one by iterating over its properties and copying them on the primitive level. Like this: ```js run let user = { name: "John", age: 30 }; *!* let clone = {}; // the new empty object // let's copy all user properties into it for (let key in user) { clone[key] = user[key]; } */!* // now clone is a fully independent object with the same content clone.name = "Pete"; // changed the data in it alert( user.name ); // still John in the original object ``` Also we can use the method [Object.assign](mdn:js/Object/assign) for that. The syntax is: ```js Object.assign(dest, [src1, src2, src3...]) ``` - The first argument `dest` is a target object. - Further arguments `src1, ..., srcN` (can be as many as needed) are source objects. - It copies the properties of all source objects `src1, ..., srcN` into the target `dest`. In other words, properties of all arguments starting from the second are copied into the first object. - The call returns `dest`. For instance, we can use it to merge several objects into one: ```js let user = { name: "John" }; let permissions1 = { canView: true }; let permissions2 = { canEdit: true }; *!* // copies all properties from permissions1 and permissions2 into user Object.assign(user, permissions1, permissions2); */!* // now user = { name: "John", canView: true, canEdit: true } ``` If the copied property name already exists, it gets overwritten: ```js run let user = { name: "John" }; Object.assign(user, { name: "Pete" }); alert(user.name); // now user = { name: "Pete" } ``` We also can use `Object.assign` to replace `for..in` loop for simple cloning: ```js let user = { name: "John", age: 30 }; *!* let clone = Object.assign({}, user); */!* ``` It copies all properties of `user` into the empty object and returns it. ## Nested cloning Until now we assumed that all properties of `user` are primitive. But properties can be references to other objects. What to do with them? Like this: ```js run let user = { name: "John", sizes: { height: 182, width: 50 } }; alert( user.sizes.height ); // 182 ``` Now it's not enough to copy `clone.sizes = user.sizes`, because the `user.sizes` is an object, it will be copied by reference. So `clone` and `user` will share the same sizes: Like this: ```js run let user = { name: "John", sizes: { height: 182, width: 50 } }; let clone = Object.assign({}, user); alert( user.sizes === clone.sizes ); // true, same object // user and clone share sizes user.sizes.width++; // change a property from one place alert(clone.sizes.width); // 51, see the result from the other one ``` To fix that, we should use the cloning loop that examines each value of `user[key]` and, if it's an object, then replicate its structure as well. That is called a "deep cloning". There's a standard algorithm for deep cloning that handles the case above and more complex cases, called the [Structured cloning algorithm](https://html.spec.whatwg.org/multipage/structured-data.html#safe-passing-of-structured-data). We can use recursion to implement it. Or, not to reinvent the wheel, take an existing implementation, for instance [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep) from the JavaScript library [lodash](https://lodash.com). ## Summary Objects are assigned and copied by reference. In other words, a variable stores not the "object value", but a "reference" (address in memory) for the value. So copying such a variable or passing it as a function argument copies that reference, not the object. All operations via copied references (like adding/removing properties) are performed on the same single object. To make a "real copy" (a clone) we can use `Object.assign` for the so-called "shallow copy" (nested objects are copied by reference) or a "deep cloning" function, such as [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep).