Screenshot 2023-11-11 at 12.20.57 PM.png

Riddle Me This - the Many Uses of the '?' Operator in Javascript

In the mysterious world of Javascript, the ? operator is an enigma that can take many forms. Its behavior changes based on its surroundings, unlocking new powers as summoned by the code around it. When a ? is used in JavaScript, its purpose is a riddle that can only be solved by understanding the context where it is used. This post will break down the different functions of the ? operator and shed some light on their origins.  

1. Ternary Operator: The Riddle of Conditionals

The Ternary (or Conditional) Operator is a shorthand for expressing conditional statements in a single line, providing a way to evaluate a Boolean expression and return one of two values based on whether the expression is true or false. It's an alternative to using if/else blocks that can also be more readable. 

const characters = [
  { name: 'Riddler', isVillain: true },
  { name: 'Batman', isVillain: false },
  { name: 'Penguin', isVillain: true },
  { name: 'Joker', isVillain: true }
];

const villainCount = characters.filter(char => char.isVillain).length;
const villainStatus = villainCount > 0 ? `There are ${villainCount} villains` : 'No villains detected';
console.log(villainStatus); // Output: There are 3 villains

Note: The conditional (ternary) operator is the only JavaScript operator that takes three operands

2. Optional Chaining: Navigating the Batcave Safely

The optional chaining (?.) operator accesses an object's property or calls a function. If the object accessed or function called using this operator is undefined or null, the expression short circuits and evaluates to undefined instead of throwing an error.

const characters = [
  { name: 'Riddler', equipment: { vehicle: undefined } },
  { name: 'Batman', equipment: { vehicle: 'Batmobile' } },
  { name: 'Penguin', equipment: { vehicle: 'Penguin Submarine' } },
  { name: 'Joker', equipment: { vehicle: 'Jokermobile' } }
];

// Using Optional Chaining
const riddlerVehicleWithChaining = characters.find(char => char.name === 'Riddler')?.equipment?.vehicle ?? 'No specified vehicle';
console.log(`Riddler's Vehicle (with Optional Chaining): ${riddlerVehicleWithChaining}`);
// Output: Riddler's Vehicle: No specified vehicle

// Without Optional Chaining
const riddlerVehicleWithoutChaining = characters.find(char => char.name === 'Riddler').equipment.vehicle ?? 'No specified vehicle';
console.log(`Riddler's Vehicle (without Optional Chaining): ${riddlerVehicleWithoutChaining}`);
// Output: TypeError: Cannot read property 'vehicle' of undefined
// (Uncaught TypeError: Cannot read property 'vehicle' of undefined)

Just as Batman navigates the Batcave's twists and turns, the Optional Chaining operator ensures safe traversal through potentially undefined properties, shielding your code from unexpected pitfalls.

Note: Optional Chaining & Nullish Coalescing were added to the JavaScript ECMAScript specification in 2020 with version ES11/2020.

3. Nullish Coalescing: Gotham's Default Value Protector

Nullish Coalescing, like Batman himself, stands guard against null and undefined threats, providing a default value when the danger is imminent.

const characters = [
  { name: 'Riddler', age: 35 },
  { name: 'Batman' },
  { name: 'Penguin', age: 45 },
  { name: 'Joker' }
];

// With Nullish Coalescing
const jokerAgeWithCoalescing = characters.find(char => char.name === 'Joker').age ?? 'Unknown';
console.log(`Joker's Age (with Nullish Coalescing): ${jokerAgeWithCoalescing}`);
// Output: Joker's Age (with Nullish Coalescing): Unknown

// Without Nullish Coalescing (This will throw an error if the age is undefined)
const jokerAgeWithoutCoalescing = characters.find(char => char.name === 'Joker').age;
console.log(`Joker's Age (without Nullish Coalescing): ${jokerAgeWithoutCoalescing}`);
// Output: Joker's Age (without Nullish Coalescing): undefined

FAQ

Can the ternary operator be nested, and if so, how does it affect readability?

Yes, the ternary operator can be nested within another ternary operation to handle more complex conditions. However, while this can make your code more concise, it can also make it harder to read and understand, especially for those new to programming. It's like putting a puzzle within a puzzle. When nesting ternaries, it's essential to keep your code as clear as possible, perhaps by breaking it down into smaller parts or opting for traditional if/else statements in more complex scenarios.

TLDR: Yes... but don't do it.

What happens if I use optional chaining on a function call, and the function is not defined?

If you use optional chaining on a function call and the function is not defined, the operation will safely return undefined instead of throwing an error. It's like knocking on a door with optional chaining; if nobody's home (the function doesn't exist), you'll just quietly walk away without causing a fuss (no error thrown).

Can nullish coalescing and optional chaining be used together in the same expression?

Yes, nullish coalescing and optional chaining can be used together in the same expression to provide even more robust code handling. This combination allows you to safely navigate through an object and provide a default value if the property is either undefined or null. It's like having a safety net while walking a tightrope; optional chaining ensures you won't fall if the rope breaks (the property doesn't exist), and nullish coalescing ensures you have something soft to land on if you do (providing a default value).

Conclusion

Mastering the many uses of the ? operator will help you navigate the mysterious world of JavaScript. By understanding the Ternary Operator, Optional Chaining, and Nullish Coalescing, you'll be well equipped to solve any riddles your code may throw at you.