All primitive types interact by value.
First, we declare two variables a and b. Then, we set b equal to a, which is 4 at that point. Later, we give a the value of 2. At this point, b is still 4! This happens because b has its own space in memory!
All non-primitive values interact by reference when setting them equal to each other or passing them to a function.
In memory, this would look something like:
Both c and d have the same value, which points to the same address.
Variable c holds a reference to an array (object) . Later, we assign d with the same reference that c has to the object. If you later change the value of that variable by, for example, pushing an element to that array, it also means that that property is changed for all the other variables. They point to the actual same object, and not a copy of it.