-2

Can anyone explain to me why the output value is changed to "20, 2" instead of the original "1, 2"?

<!DOCTYPE html>
<html>
<body>
  <p id="demo"></p>
  <p id="demo1"></p>
  <script>
    var x = {
      a: 1,
      b: 2
    };
    var y = x;
    y.a = 20;
    document.getElementById("demo").innerHTML = x.a;
    document.getElementById("demo1").innerHTML = x.b;
  </script>
</body>
</html>

4
  • 2
    JS passes objects by reference, there are some in depth questions relating to this: stackoverflow.com/questions/16880418/… Commented Sep 9, 2019 at 10:23
  • Since you seem to be new to JavaScript, I highly suggest not using var as it is considered bad practice. You should use let or const. Commented Sep 9, 2019 at 10:26
  • 3
    @Seblor I would argue that there's nothing wrong with using var in front end JS, in fact if you're aiming for a good range of browser support, we're still (unfortunately) on the border of having to avoid using let/const at all. Commented Sep 9, 2019 at 10:28
  • @DBS While I understand what you mean, I really think the use of var and the browser support should be left to the transpilers (like Babel). If people keep using var, they will have a hard time changing later on. Also using the newer ECMAScript versions usually improves the code readability. Commented Sep 9, 2019 at 12:10

4 Answers 4

2

You are pointing y to the reference of x which itself is pointing to the object {a:1,b:2}.

So in memory it is:

x --> {a:1,b:2}

After you do y = x, it becomes:

y --> x --> {a:1,b:2}

Or to put it simply:

x --> {a:20,b:2}
         ^
         |
y -------

Now when you do y.a = 20, since y and x are both pointing to the same object when properties of the object is changed through either of the references x or y the change will be reflected in both the references:

y --> {a:20,b:2}
        ^
        |
x -------

That is why you get 20,2 when you get x.a.

Sign up to request clarification or add additional context in comments.

Comments

1
var y=x

In the above line y is passed the reference of x instead of the whole object x. Any changes made to the object will get reflected in all the variables containing the reference of the object.

Comments

1

Because its the same reference (same address for memory location where the object is stored) both x and y are now the same reference so changing one will change the value stored, and now as they are the same reference they will output the same object values.

I would add something extra to make this answer more productive.

Shallow -Copy

Shallow copy is a bit-wise copy of an object. A new object is created that has an exact copy of the values in the original object. If any of the fields of the object are references to other objects, just the reference addresses are copied i.e., only the memory address is copied.

example

let x={"a":1,"b":2};
let y=x;  //It makes a copy of the reference to x into y

So, the addresses of x and y will be the same i.e. they will be pointing to the same memory location. so if you do this

y.a=9;

and now when you print y on the screen

console.log(y) // it prints {"a":9,"b":2};

but the interesting fact here is , when you print x

console.log(x)  // it also prints {"a":9,"b":2};

So Now how to change this scenario??. The solution is a deep copy

Deep copy

A deep copy copies all fields and makes copies of dynamically allocated memory pointed to by the fields. A deep copy occurs when an object is copied along with the objects to which it refers.

in Lehman terms you create a variable y allocate it a different memory location, copy all the members of x, assign the copied members to y

the easiest way to do it is by stringifying the object

let y=JSON.parse(JSON.stringify(x))

now if we do

y.a=9

and print y

console.log(y) // it prints {"a":9,"b":2};

and if we print x

console.log(x) //  it prints {"a":1,"b":2};

/// shallow copy

let x = {
  "a": 1,
  "b": 2
};
let y = x;
y.a = 9;
console.log(y);
console.log(x);


// Deep Copy

let z = {
  "a": 1,
  "b": 2
};
let t = JSON.parse(JSON.stringify(z));
t.a = 9;
console.log("z:", z);
console.log("t:", t);
This scenario becomes more fun when we have nested objects

let c = {
  "a": {
    "A": 1
  },
  "b": {
    "B": 2
  }
};
let t = Object.assign({}, c); // It is also shallow copying
t.a.A = "7"; // since a is a nested object so again reference is passed
console.log(c);
console.log(t)
console.log("Second Scenario-------------------")


let d = {
  "a": {
    "A": 1
  },
  "b": {
    "B": 2
  }
};
let k = JSON.parse(JSON.stringify(d));
k.a.A = 88
console.log(d)
console.log(k)

Comments

0

That is because y & x both point to same memory location.If you want a separate copy , then deep copy the object. JSON.parse & JSON.stringify

var x = {
  a: 1,
  b: 2
};
var y = JSON.parse(JSON.stringify(x));
y.a = 20;
document.getElementById("demo").innerHTML = x.a;
document.getElementById("demo1").innerHTML = x.b;
<p id="demo"></p>
<p id="demo1"></p>

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.