Bootcamp
Search…
0.2.4: Reference vs. Value
In JavaScript, and any language that has automatic memory management, the creation of data types like arrays and objects has special behaviours.
Specifically, JavaScript has this potentially confusing behaviour:
var array1 = [1,2,3];
var array2 = array1;
array1.pop(); // get rid of one element of the array
array2.length; // this will be 2 - the same as array1
When assigning an array (or object) to a variable as we did on line 2 above, any action done on the array1 variable also happens to the array2 variable. Why is this?
Try this example above. Is there anything that can be done to array1 that doesn't affect array2?

Memory

The word memory in computing can have different meanings depending on the context. We'll discuss this JavaScript behaviour in the context of RAM memory, the part of the computer that holds variable values from the beginning to the end of the life of the program. (For instance RAM holds a global variable from script.js when the page loads until the window is refreshed or closed.)
The structure of RAM memory is like a grid that holds "primitive" values, i.e., numbers and strings. The terms 32-bit and 64-bit actually refers to the size of the values that can be held in one square of this memory grid.
This count variable can contain a value from 0 to 64 bit places (2⁶⁴), or 18,446,744,073,709,551,616 in base 10.
var count = 15;
Think about the way an array or object can hold values- it's fundamentally different from holding a primitive value. This counts variable can hold an undetermined amount of number values that can each be from 0 to 18,446,744,073,709,551,616. It would be impossible for this single variable to fit in one square of the memory grid.
var counts = [2,5,6,7]
Variables can hold primitive values or complex values.
The way that JavaScript solves this is to hold one square for the variable itself, and then one square for each value it holds. This also allows for cases where an array contains another array, or other nested structures. Remember that there is no real limit on the level of nesting of an array or object- e.g., an array that holds an array that holds an array, etc.
No need to worry for now how JavaScript manages to keep track and manage these values for use in an object or array. We'll cover the topic regarding objects in DS&A D.6.2: Hash Tables.
Video on computer memory: https://www.youtube.com/watch?v=fVVrfJM4JeY​

Reference vs. Value

Now let's revisit the original example. When we assign the value of array1 to a new variable array2, all we do is copy that reference to the array into a new variable. That reference still refers to the same squares.
When we run an operation on one variable, like pop, array2 variable references the values from the original variable.
var array1 = [1,2,3];
var array2 = array1;
array1.pop(); // get rid of one element of the array
array2.length; // this will be 2 - the same as array1
So, in this context, the word reference is talking about the fact that an array variable references the values inside.
Contrast this with variables that hold actual primitive values:
var count = 2;
var count2 = count;
Line 2 above copies the value of the variable count into the new variable count2.
In the first example the array1 reference is copied into the new variable array2.
Video on Reference vs Value: https://www.youtube.com/watch?v=-hBJz2PPIVE​
Video on how arrays are stored: https://www.youtube.com/watch?v=pmN9ExDf3yQ​

Fixes

How do we get around this behaviour? The solution depends on the data in the variable:

Simple fix: Non-nested values

If there are no arrays or objects in the variable, ES6 can be used.
var array1 = [1,2,3];
var array2 = [...array1];
ES6 spread operator will make a copy of every value in the array into a new array. See: 0.2.3.​

Hack: Copy all nested values except functions

If you have data that is nested, like an array in an array, you can use this hack that makes the data into a string, then back into a variable value.
var oldObject = {
name: 'A',
address: {
street: 'Station Road',
city: 'Pune'
}
}
var newObject = JSON.parse(JSON.stringify(oldObject));
​
newObject.address.city = 'Delhi';
console.log('newObject');
console.log(newObject);
console.log('oldObject');
console.log(oldObject);

True "deep copy": Copy all values into a new copy

JavaScript doesn't provide any standard way of doing this, except for writing some kind of loop to go over the structure and create a new structure. See the links below for some examples.

Conclusion

There should be two key takeaways from this section:
  1. 1.
    Don't write code that directly assigns an object, array or class instance to another variable. You probably meant to make a copy.
  2. 2.
    These fixes above are generally enough without having to deep copy a variable- but this simply depends on what is in your variable.

Further Reading