Per specification, section 11.11: Binary Logical Operators:
The production [of evaluating &&] ... is evaluated as follows:
- Let lref be the result of evaluating LogicalANDExpression.
- Let lval be GetValue(lref).
- If
ToBoolean(lval) is false, return lval.
- Let rref be the result of evaluating BitwiseORExpression.
- Return GetValue(rref).
The production [of evaluating ||] ... is evaluated as follows:
- Let lref be the result of evaluating LogicalORExpression.
- Let lval be GetValue(lref).
- If
ToBoolean(lval) is true, return lval.
- Let rref be the result of evaluating LogicalANDExpression.
- Return GetValue(rref).
So internally the value is "converted to a boolean". However, since this is never exposed -- and the entire semantic explanation is an abstraction which can be/is "optimized out" -- the behavior of && and || can be simply explained through using truthy-and-falsy values (for which ToBoolean covers: a truthy-value is one for which ToBoolean returns true, all other values are falsy).
The logical table for && is:
a b result
truthy any b
falsy any a
The logic table for || is:
a b result
truthy any a
falsy any b
Note that either the evaluation of a or b is returned.
Happy coding.
For completeness, from section 9.2:
The abstract operation ToBoolean converts its argument to a value of type boolean as ...
- Undefined - false
- Null - false
- boolean (not Boolean object!) - The result equals the input argument (no conversion).
- number (not Number object!) - The result is false if the argument is +0, -0, or NaN; otherwise the result is true.
- string (not String object!) - The result is false if the argument is the empty String (its length is zero); otherwise the result is true.
- Object - true