Values vs. References

In Chapter 2, we introduced the two main types of values: primitives and objects. But we didn’t discuss yet one key difference between the two: how these values are assigned and passed around.

In many languages, the developer can choose between assigning/passing a value as the value itself, or as a reference to the value. In JS, however, this decision is entirely determined by the kind of value. That surprises a lot of developers from other languages when they start using JS.

If you assign/pass a value itself, the value is copied. For example:

  1. var myName = "Kyle";
  2. var yourName = myName;

Here, the yourName variable has a separate copy of the "Kyle" string from the value that’s stored in myName. That’s because the value is a primitive, and primitive values are always assigned/passed as value copies.

Here’s how you can prove there’s two separate values involved:

  1. var myName = "Kyle";
  2. var yourName = myName;
  3. myName = "Frank";
  4. console.log(myName);
  5. // Frank
  6. console.log(yourName);
  7. // Kyle

See how yourName wasn’t affected by the re-assignment of myName to "Frank"? That’s because each variable holds its own copy of the value.

By contrast, references are the idea that two or more variables are pointing at the same value, such that modifying this shared value would be reflected by an access via any of those references. In JS, only object values (arrays, objects, functions, etc.) are treated as references.

Consider:

  1. var myAddress = {
  2. street: "123 JS Blvd",
  3. city: "Austin",
  4. state: "TX"
  5. };
  6. var yourAddress = myAddress;
  7. // I've got to move to a new house!
  8. myAddress.street = "456 TS Ave";
  9. console.log(yourAddress.street);
  10. // 456 TS Ave

Because the value assigned to myAddress is an object, it’s held/assigned by reference, and thus the assignment to the yourAddress variable is a copy of the reference, not the object value itself. That’s why the updated value assigned to the myAddress.street is reflected when we access yourAddress.street. myAddress and yourAddress have copies of the reference to the single shared object, so an update to one is an update to both.

Again, JS chooses the value-copy vs. reference-copy behavior based on the value type. Primitives are held by value, objects are held by reference. There’s no way to override this in JS, in either direction.