4

I am new to JS and was learning value and reference types in JS but I faced some confusion on the below code:

const obj = {
  arr: [{
    x: 17
  }]
};

let z = obj.arr;

z = [{
  x: 25
}];

console.log(obj.arr[0].x);

The above code outputs 17 but why? Well, arr is a reference type, that is, it is mutable then we equalize obj.arr to variable z so z holds reference to arr array in obj object. Finally, z holding 17 then we change it to 25 but it output 17.

FZs
  • 16,581
  • 13
  • 41
  • 50
Dickens
  • 895
  • 3
  • 11
  • 25

4 Answers4

3

First time, you have something like this:

obj ---> {
           arr ---+
         }        |
                  |
                  v
                  [
                     [0] ---+
                  ]         |
                  ^         |
                  |         v
                  |         { x: 17 }
                  |
                  |
z ----------------+

Note that z now points to the same object as obj.arr but not to obj.arr.

Reassigning z changes only what z points to, but it doesn't affect obj.arr; it refers to the same object as before:

obj ---> {
           arr ---+
         }        |
                  |
                  v
                  [
                     [0] ---+
                  ]         |
                            |
                            v
                            { x: 17 }
                  
                  
z ----> [
          [0] ----> { x: 25 }
        ]

That's why obj.arr didn't change.

But how to change it via z, you might ask?

You can't change obj.arr itself, but you can still mutate it.

Instead of your code, you can use this:

z[0] = { x:25 }

Now you have:

obj ---> {
           arr ---+
         }        |
                  |
                  v
                  [
                     [0] ---> { x: 25 }
                  ]         
                  ^         
                  |        
                  |         { x: 17 } -----> Garbage collection
                  |
                  |
z ----------------+

const obj = {
    arr: [{ x: 17 }]
};

let z = obj.arr;

z[0] = { x: 25 };

console.log(obj.arr[0].x);
FZs
  • 16,581
  • 13
  • 41
  • 50
1
const obj = {
 arr: [{ x: 17 }]
};

/**
 * z -> it is only reference to original object (const obj in our case). 
 * It is like another door to the same room
 */
let z = obj.arr;

/*
 * now z -> points to other value (array), but previous still exist
 */
z = [{ x: 25 }]; 

console.log(obj.arr[0].x);
0

You've just created z, which is a copy of obj.arr . If you change the value of z, the copy, the original (obj.arr) do not change.

I'm French that's why my english isn't perfect

  • 2
    I wouldn't say that `z` is a copy of `obj.arr`. "`z` refers to the same array as `obj.arr`" (the one with 17 in it) might be a better way to say it. After doing `z = [{ x: 25 }]`, `z` refers to a new array (the one with 25 in it). And `obj.arr` still refers to the first array (the one with 17 in it). – Wyck Sep 25 '19 at 17:07
0

The reference to obj.arr is replaced. z = [{ x: 25 }]; simply creates a new array with a new object, { x: 25 }, inside it. Then, it places a reference to this new array into z.

BCDeWitt
  • 4,540
  • 2
  • 21
  • 34