How does copy objects work?

3
var a = {a: 1, b: 2};
var b = a;

b.a = 3;  

In the above code, b.a becomes 3, and a.a also becomes 3.

var a = {a: 1, b: 2};

function b(objeto) {
    objeto.a = 3;
}

b(a);

In the above code, the value of a.a remains 1, since I am not editing the object a, but a copy of it (correct me if I am wrong).

Now here's the question:

var a = {a: 1, b: 2};

function copy(objeto) {
    return objeto;
}

var b = copy(a);

b.a = 3;

In the code above, a.a is also worth 3. Why?

    
asked by anonymous 28.04.2016 / 19:59

4 answers

3

Your second guess is wrong, see:

var a = {a: 1, b: 2};

function b(objeto) {
    objeto.a = 3;
}

b(a);

document.write(JSON.stringify(a));

a.a becomes 3 when you do objeto.a = 3; , so the second code has the same result as the third.

The main point you need to understand is that objects in JS are always passed by reference, so changing attributes of them in the function to which they were passed will always result in the original object being changed. Please read in this answer to understand how it works.

    
28.04.2016 / 20:12
2

Objects passed by reference always change the original.

In your second example what happens is the same as in the first one:

function b(objeto) {
    objeto.a = 3;
    console.log(objeto.a); // 3
}

b(a);
console.log(a.a); // 3

The third version of the code is basically the same as the second. The result you get is the same with the semantic difference that the function of the third example has no return.

    
28.04.2016 / 20:14
2

JS works the objects as reference. That is, the object variable is just the memory address where the data is.

The object type (which in the background is an array ) is the only type by reference. The other JS data types are by value, so the variable stores the value itself and not an address where the value is.

Example 1

So if you copy the value of this variable to another ( object address ), you will only have two variables pointing to the same object, so any changes to this object will reflect both variables.

Example 2

A parameter is just a variable that takes a value. If this value is an address of an object , it is a copy of that value, but not of the object. In the background the same thing happens as the previous case.

Example 3

Here the function receives the object's address and then returns it to the caller. This result is stored in a variable. In the background it was the same thing here too.

var a = {a: 1, b: 2};

var b = a;
b.a = 3; 
document.body.innerHTML += a.a; //imprime 3

function change(objeto) {
    objeto.a = 3;
}

change(a);
document.body.innerHTML += a.a; //imprime 3

function copy(objeto) {
    return objeto;
}

var b = copy(a);
b.a = 3;
document.body.innerHTML += a.a; //imprime 3
    
28.04.2016 / 20:18
1

I know you already have your explanation, but I would like to mention the Object.assign , which serves just to merge objects:

var a = { a: 1, b: 2, c: 3 };
var b = Object.assign({}, a);

b.a = 4;

console.log(a, b);

However, depending on the browsers you want to support, you may have to use the following Polyfill:

if (!Object.assign) {
  Object.defineProperty(Object, 'assign', {
    enumerable: false,
    configurable: true,
    writable: true,
    value: function(target) {
      'use strict';
      if (target === undefined || target === null) {
        throw new TypeError('Cannot convert first argument to object');
      }

      var to = Object(target);
      for (var i = 1; i < arguments.length; i++) {
        var nextSource = arguments[i];
        if (nextSource === undefined || nextSource === null) {
          continue;
        }
        nextSource = Object(nextSource);

        var keysArray = Object.keys(Object(nextSource));
        for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
          var nextKey = keysArray[nextIndex];
          var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
          if (desc !== undefined && desc.enumerable) {
            to[nextKey] = nextSource[nextKey];
          }
        }
      }
      return to;
    }
  });
}
    
28.04.2016 / 20:43