Short Circuiting
- 3 properties of the && and || operators:
- they can use any data type
- they can return any data type (=> they are not only for booleans)
- short-circuit evaluation
||
- if the first operand is truthy then the expression it true, so the first operand will be returned and the second operand will not even be evaluated --- meaning it is skipped/not looked at => the evaluation is short circuited
- if the first operand is falsy then the second operand will be evaluated and returned as the default value
console.log(3 || 'Jonas') // 3
console.log('' || 'Jonas') // Jonas
console.log(true || 0) // true
console.log(undefined || null) // null
Generalized
- not just for 2 operands
- the first truthy operand will be returned --- any following operands will be short circuited
console.log(undefined || 0 || '' || 'Hello' || 23 || null) // Hello
Using in Place of Ternary
- this is the final version of the example code from spread_and_rest.md:
const restaurant = {
name: 'Classico Italiano',
location: 'Via Angelo Tavanti 23, Firenze, Italy',
categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
mainMenu: ['Pizza', 'Pasta', 'Risotto'],
operatingHours: {
thu: {
open: 12,
close: 22,
},
fri: {
open:11,
close: 23,
},
sat: {
open: 0, // open 24 hours
close:24
},
},
order: function(starterIndex, mainIndex) {
return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]]
},
orderDelivery: function ({
starterIndex = 1,
mainIndex = 0,
time = '20:00',
address,
}) {
console.log(`Order recieved! ${this.starterMenu[starterIndex]} and ${this.mainMenu[mainIndex]} will be delivers to ${address} at ${time}`)
},
orderPasta: function (ing1, ing2, ing3) {
console.log(`Here is your delicious pasta with ${ing1}, ${ing2}, and ${ing3}.`)
},
orderPizza: function (mainIngredient, ...additionalIngredients) {
// just going to log them here, but really you'd do something with the ingredients
console.log(mainIngredient)
console.log(additionalIngredients)
},
}
- using ternary:
const guests = restaurant.numGuests ? restaurant.numGuests : 10 console.log(guests) // 10
numGuests
doesn't exist so it isundefined
, which is falsy, so 10 is returned- if we set the
numGuests
property then that number will be returned
restaurant.numGuests = 23 const guests = restaurant.numGuests ? restaurant.numGuests : 10 console.log(guests) // 23
- using short circuiting:
const guests = restaurant.numGuests || 10 console.log(guests) // 10
restaurant.numGuests = 23 const guests = restaurant.numGuests || 10 console.log(guests) // 23
- NOTE: neither of the 2 solutions just shown (ternary or short circuiting) will work if
restaurant.numGuests = 0
--- 0 is a falsy value so they will both return 10 so make sure to be sure to account for this in real use cases
&&
- works the opposite of the
||
operator - it short circuits at the first value is falsy and returns that operand without evaluating any following it
console.log(0 && 'Jonas') // 0
console.log(7 && 'Jonas') // Jonas
console.log('Hello' && 23 && null && 'Jonas') // null
Using in Place of If Statement
- using if statement:
if (restaurant.orderPizza) { restaurant.orderPizza('mushrooms', 'spinach') // mushrooms // ▶ ["spinach'] }
- i.e. if the function exists then we call it
- using short circuiting:
restuarant.orderPizza && restuarant.orderPizza('mushrooms', 'spinach')
- if the function doesn't exist it short circuits --- if it does exist then it evaluates the next operand which calls the function
NOTE: just because you can, doesn't mean you should replace an if
or ternary with &&
or ||
--- they can often make code more confusing, so use with thoughtfulness