Write more prudent Javascript with these tricks

Have a look at the following code sample:

data.course.enrolments.forEach(enrolment => enrolment.confirm())

Sometimes the data we work with is not predictable, so to avoid errors or crashes we always have to take care of edge cases. The above code makes a lot of assumptions. It assumes that data.course exists, data.course.enrolments exists and is an array of objects with a confirm property which is a valid Function.

If the data.course or data.course.enrolments property is undefined we get the following TypeError error:

Uncaught TypeError: Cannot read property enrolments of undefined
  Uncaught TypeError: Cannot read property forEach of undefined

If the confirm property in each enrolment object in the data.course.enrolments array is not a valid Function, we get the following error:

Uncaught TypeError: enrolment.confirm is not a function

Now have a look at this one:

((data.course || {}).enrolments || []).forEach(enrolment => enrolment.confirm && enrolment.confirm())

I'll explain how the above snippet works.

data.course || {}

This expression resolves to data.course if the course property exists on the data object, and resolved to an {} if it doesn't. The reason it resolves to {} is because of the || operator which checks if the left-hand side of the expression (data.course) is falsy, and if it is, resolves the expression to the right-hand side ({}). If it's not falsy then it resolved the expression to the left-hand side.

(data.course || {}).enrolments || [])

As explained above, the left-hand side will either be data.course or {}. Next, we try to access the enrolments property on the object resolved from the first expression.

enrolment.confirm && enrolment.confirm()

Unlike the || operator, the && checks if the left-hand side of the expression (enrolment.confirm) is truthy, and if it is, resolves the expression to be the right-hand side (enrolment.confirm()). This means the function enrolment.confirm will never be executed if the confirm property is not found on the enrolment object.

Summary

Taking care of edge cases as you write your code can save you a lot of debugging time, and also prevent unexpected application crashes.