How does object copying work?

Asked

Viewed 135 times

3

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

b.a = 3;  

In the code above, b. a becomes worth 3, and a. a also becomes worth 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, because 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 also worth 3. Why?

  • I couldn’t reproduce your result from the second snippet of code: Exception: TypeError: objeto is undefined.

  • Code corrected, Pablo.

  • it seems that he is simply linking object a with b I will put a way I found to make cloning

  • Now a.a remains 3.

  • The closest and simplest to cloning an object would be like this: var copiedObject = jQuery.extend({}, originalObject)

  • If you intend to obtain a complete copy at all times, take a look at this question: http://answall.com/a/881/26404

  • The second code shall include the a changed to 3. The object is passed by reference. You are changing the object itself and not a copy.

  • My goal is not to make a copy. I want to understand why this happens. What is the difference between the second code and the third code? Why one modifies the object and another does not?

Show 3 more comments

4 answers

4


Your second assumption 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 real 3 when you do objeto.a = 3;, then the second code has identical result to the third.

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

  • Bruno, this only happens with objects or variables are also passed as reference?

  • @André only objects and arrays (arrays are more or less objects in js, it’s kind of confusing), values are copied. Read the post that Linkei, there details this well.

  • @André Primitive are not passed by reference. Brunobr: +1

  • When you say they are passed by reference, are you talking about assignment or passing by parameter? Because the parameters are all by value, not by reference.

  • Passing objects by parameter generates a copy of the reference, which is what makes it possible to change the values of the original object and yet does not allow you to change the reference of the original object. As I said before this answer already detail well the operation.

  • Yes, but an assignment also generates a copy of the reference. It is not wrong, but to say so seems that a parameter passage is different from an assignment, which in JS is not (referring to the value that is passed).

Show 1 more comment

3

JS works objects as reference. That is, the object variable is only the memory address from which the data is.

The object type (which at the bottom is a array) is the only type considered a 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 (address of the object), will only have two variables pointing to the same object, so any change in this object will reflect the two variables.

Example 2

A parameter is only a variable that receives a value. If this value is a address of an object, is a copy of this value, but not of the object. In the background occurs the same thing as the previous case.

Example 3

Here the function receives the address of the object and then returns it to the caller. This result is saved in a variable. At the bottom the same thing occurred 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

I put in the Github for future reference.

2

Objects passed by reference always change the original.

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

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 that obtêns is the same with the semantic difference that the function of the third example has no return.

1

I know you have your explanation, but I’d like to mention Object.assign, which serves precisely to merge objects:

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

b.a = 4;

console.log(a, b);

But if you need the browsers you want to support, you may need 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;
    }
  });
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.