The and-operator (&&
) and the or-operator (||
) employ short-circuiting to prevent unnecessary work if the outcome of the operation does not change with the extra work.
In x && y
, y
will not be evaluated if x
evaluates to false
, because the whole expression is guaranteed to be false
.
In x || y
, y
will not be evaluated if x
evaluated to true
, because the whole expression is guaranteed to be true
.
Example with functions
Take the following two functions:
function T() { // True
console.log("T");
return true;
}
function F() { // False
console.log("F");
return false;
}
Example 1
T() && F(); // false
Output:
'T'
'F'
Example 2
F() && T(); // false
Output:
'F'
Example 3
T() || F(); // true
Output:
'T'
Example 4
F() || T(); // true
Output:
'F'
'T'
Short-circuiting to prevent errors
var obj; // object has value of undefined
if(obj.property){ }// TypeError: Cannot read property 'property' of undefined
if(obj.property && obj !== undefined){}// Line A TypeError: Cannot read property 'property' of undefined
Line A: if you reverse the order the first conditional statement will prevent the error on the second by not executing it if it would throw the error
if(obj !== undefined && obj.property){}; // no error thrown
But should only be used if you expect undefined
if(typeof obj === "object" && obj.property){}; // safe option but slower
Short-circuiting to provide a default value
The ||
operator can be used to select either a "truthy" value, or the default value.
For example, this can be used to ensure that a nullable value is converted to a non-nullable value:
var nullableObj = null;
var obj = nullableObj || {}; // this selects {}
var nullableObj2 = {x: 5};
var obj2 = nullableObj2 || {} // this selects {x: 5}
Or to return the first truthy value
var truthyValue = {x: 10};
return truthyValue || {}; // will return {x: 10}
The same can be used to fall back multiple times:
envVariable || configValue || defaultConstValue // select the first "truthy" of these
Short-circuiting to call an optional function
The &&
operator can be used to evaluate a callback, only if it is passed:
function myMethod(cb) {
// This can be simplified
if (cb) {
cb();
}
// To this
cb && cb();
}
Of course, the test above does not validate that cb
is in fact a function
and not just an Object
/Array
/String
/Number
.