-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>
Ashu
  • 2,066
  • 3
  • 19
  • 33
Kai Ye
  • 29
  • 1
  • 2
    JS passes objects by reference, there are some in depth questions relating to this: https://stackoverflow.com/questions/16880418/javascript-pass-object-as-reference – DBS Sep 09 '19 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`. – Seblor Sep 09 '19 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. – DBS Sep 09 '19 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. – Seblor Sep 09 '19 at 12:10

4 Answers4

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.

Fullstack Guy
  • 16,368
  • 3
  • 29
  • 44
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.

ellipsis
  • 12,049
  • 2
  • 17
  • 33
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)
Shubham Dixit
  • 9,242
  • 4
  • 27
  • 46
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>
brk
  • 48,835
  • 10
  • 56
  • 78