17

This may be an old question but I'm really curious about the nature of copying objects by reference as an assignment in javascript.

Meaning that if

var a = {}; 
var b = a;
a.name = "Renato";
console.log(b); 
Object {name: "renato"}

I'm kind of new to javascript and this really caught my attention to have a shallow copy as a default for Object assignment. I searched that in order to create a hard copy, you have to create a mixin. I was wondering why was this chosen as the default since it's transformation seems to be very implicit. Thanks!

Renato Francia
  • 803
  • 1
  • 12
  • 23
  • 1
    `wondering why was this chosen as the default` Because in most cases it would be the best option, .. Javascript is a Garbage Collected environment, one of it's strengths is be able to pass objects about without having to worry about memory leaks. And the other advantage is speed.. – Keith Nov 05 '16 at 01:29
  • In addition, deep copies are more costly. Doing shallow copy by default gives the programmer the freedom to explicitly choose which one they want to perform – Alex Nov 05 '16 at 01:32

1 Answers1

29

Objects and arrays are treated as references to the same object. If you want to clone the object, there are several ways to do this.

In later browsers, you can do:

var b = Object.assign({}, a);

If you want to go for a library, lodash provides _.clone (and _.cloneDeep):

var b = _.clone(a);

If you don't want to do either of those methods, you can just enumerate through each key and value and assign them to a new object.

Oftentimes it's valuable for them to be treated as references when passing through multiple functions, etc. This isn't the case for primitives like numbers and strings, because that would feel pretty counterintuitive in most cases.

Josh Beam
  • 19,292
  • 3
  • 45
  • 68
  • 3
    You could also add the good old JSON.parse/stringify.. `var b = JSON.parse(JSON.stringify(a))` – Keith Nov 05 '16 at 01:36
  • 1
    @Keith also another idea, but that won't work for objects that have functions as values. – Josh Beam Nov 05 '16 at 01:37
  • 1
    If we have `{ a: 'b', c: function(){} }`, stringifying it will result in `"'{'a':'b'}'"` – Josh Beam Nov 05 '16 at 01:38
  • 2
    Indeed, I should have mentioned if the data was serializeable.. It was just meant as another option, were if running on older browsers, you could do this without having to say load lodash/underscore etc. – Keith Nov 05 '16 at 01:41
  • 2
    If you're writing in ES6, you can also use the object spread operator: `let b = {...a};`. Looks like this isn't supported in many browsers (yet), so you should only do this if you are using a transpiler (like babel) and targeting ES5 or earlier. – AJ Richardson Aug 28 '17 at 19:37