Value and reference assignment

July 16, 2021 — 3 min read

Value and reference assignment

Data Types

When we assign a value to a variable, it can be a primitive value or a data structure.

Primitive values

The primitive values in JavaScript are: String, Number, Boolean, Null (special primitive), undefined, and Symbol. These values are immutable, so when we change a variable with any of these data types, a new reference in memory is created, the same happens when we assign a variable to another.

let value = 'Zagatti'
let newValue = value

In the example above, both variables are equal because they both contain a primitive type that can be compared within JavaScript, but if we change either of them, this change will not be reflected in the other.

This is what we can call assignment by value because the variables do not share the same reference, being independent.

Non-primitive values

In JavaScript, we can say that non-primitive values encompass the types Object and Function, which in the case of JavaScript, arrays, literal objects, Maps, etc., are of type Object.

const reference = { name: 'Zagatti' }
const newReference = { name: 'Zagatti' }

console.log(reference === newReference) // false

If we use the comparison operator between equal objects, we get a false as a result because they are different objects, containing the same information but having different references.

const reference = { name: 'Zagatti' }
const newReference = reference

console.log(reference === newReference) // true

As we can see, the comparison operator returned true, because the comparison is between the same object, which is what we can call assignment by reference.

This is the type of assignment that we should pay more attention and care to because if we change the object through any of the variables, it will be reflected in the other.

const reference = { name: 'Zagatti' }
const newReference = reference
newReference.name = 'Andre'

console.log(reference) // { name: 'Andre' }

There are many ways to create a new reference to the object, the most used is with the spread introduced in ES6.

const reference = { name: 'Zagatti' }
const newReference = { ...reference }
newReference.name = 'Andre'

console.log(reference) // { name: 'Zagatti' }

In daily life, we use a lot of arrays of objects, and in this case, it begins to become more complex to take care of the reference because we can create a new array with the spread, but we still have the same internal object references, and it becomes more complex when we have even more levels in the object with other objects.

const reference = [{ name: 'Zagatti' }]
const newReference = [...reference]
newReference[0].name = 'Andre'

console.log(reference) // [{ name: 'Andre' }]

There are several ways to clone an array or object in JavaScript, but I leave it up to you to read on the link or research more about it.

Beware of mutability

In many cases, we create functions to manipulate arrays within JavaScript. Therefore, we must be careful with certain methods that directly alter the array. Instead, in most cases, it is preferable to use methods that generate and return a new array or data.

const array = [1, 2, 3]

function removeLastItem(arr) {
  arr.splice(-1, 1)
  return arr
}

const newArray = removeLastItem(array)

console.log(array) // [1, 2]
console.log(newArray) // [1, 2]

In many cases, we want to preserve the original value, so the example with splice wouldn’t work well. For the same operation, we have the slice method.

const array = [1, 2, 3]

function removeLastItem(arr) {
  return arr.slice(null, -1)
}

const newArray = removeLastItem(array)

console.log(array) // [1, 2, 3]
console.log(newArray) // [1, 2]

The methods that mutate the array are: copyWithin, fill, flat, pop, push, reverse, shift, sort, splice, and unshift. All the others create a new data while keeping the original array intact.

Conclusion

Understanding the different data types of a language is essential to work at a high level. Without understanding the difference between assigning a value or a reference to a variable, it becomes complex to understand the data flow of the application and to predict data being changed in different contexts having the same reference spread throughout the application.

It’s not a difficult concept to understand, and I hope that at the end of this post, you have understood how to create advantages in different contexts, mutating or not your data structures.

References


André Zagatti

Frontend software engineer who likes to share knowledge.

A. Zagatti Logo

© 2023, André Zagatti