Trace the fixed program
mark records each call before returning a value. For the supplied false && and true || expressions, predict whether either right operand is reached.
const calls=[];
function mark(label,value){calls.push(label);return value;}
const a=mark('left-and',false)&&mark('right-and',true);
const b=mark('left-or',true)||mark('right-or',false);
console.log(JSON.stringify({a,b,calls}));
{"a":false,"b":true,"calls":["left-and","left-or"]}| Expression | Calls that run | Returned value |
|---|---|---|
| false && right | left-and | false |
| true || right | left-or | true |
Explain the result
&& returns a falsy left operand without evaluating the right; || returns a truthy left operand the same way. These operators return operand values, not necessarily booleans. A required action belongs in an explicit statement if it must run in every case.
Test the alternative
A required cleanup put on the right of false && is silently skipped. An empty string is also falsy and is returned as an empty string.
const calls=[];const value=''&&calls.push('cleanup');
console.log(JSON.stringify({value,calls}));
{"value":"","calls":[]}Work the boundary case
With true && and false ||, which right calls now execute?
Show the worked answer
Both right calls execute, after their respective left calls. The result is each right operand’s value.
const calls=[];function mark(label,value){calls.push(label);return value;}
const a=mark('left-and',true)&&mark('right-and',7);
const b=mark('left-or',false)||mark('right-or','ready');
console.log(JSON.stringify({a,b,calls}));
{"a":7,"b":"ready","calls":["left-and","right-and","left-or","right-or"]}