15

Flanagan's O'Reilly JavaScript book states:

Unlike the && and || operators, the ! operator converts its operand to a boolean value [...] before inverting the converted value.

If those logical operators don't convert the operands to booleans, how can the expression be evaluated?

ppecher
  • 1,978
  • 4
  • 19
  • 30
  • See also [JavaScript type conversion: (true && 1) vs (true | | 1)](http://stackoverflow.com/q/8559920/712765) – Old Pro Jun 02 '13 at 16:46

4 Answers4

11

They do convert the values to boolean, but only to determine how to proceed in evaluating the expression. The result of the expression is not necessarily boolean (in fact, if neither of your operands are boolean, it will not give you a boolean):

var x = false || 'Hello' // gives you 'Hello'
var y = 0 && 1           // gives you 0, because 0 is "falsy" and short circuits
var z = 1 || 2           // gives you 1, because 1 is "truthy" and short circuits
NullUserException
  • 83,810
  • 28
  • 209
  • 234
Pointy
  • 405,095
  • 59
  • 585
  • 614
  • It does indeed invoke `ToBoolean` (under section 11.11 of the ECMAScript ed. 5) ... no votes left, but this is correct. –  Sep 29 '11 at 18:53
  • Exactly. If you put `true && 0` into a JS console, the output will be `0`, but if you put `if(true && 0) { true; } else { false; }`, the output will be `false`. – eyelidlessness Sep 29 '11 at 18:56
  • Ha ha yes, that's true. I'm teaching it (informally) to a bunch of 13 year olds at present, and I have to wonder what they'll think when they see other boring languages someday :-) – Pointy Sep 29 '11 at 19:02
  • Thanks for elaborating on the return value – ppecher Sep 29 '11 at 20:17
5

Per specification, section 11.11: Binary Logical Operators:

The production [of evaluating &&] ... is evaluated as follows:

  1. Let lref be the result of evaluating LogicalANDExpression.
  2. Let lval be GetValue(lref).
  3. If ToBoolean(lval) is false, return lval.
  4. Let rref be the result of evaluating BitwiseORExpression.
  5. Return GetValue(rref).

The production [of evaluating ||] ... is evaluated as follows:

  1. Let lref be the result of evaluating LogicalORExpression.
  2. Let lval be GetValue(lref).
  3. If ToBoolean(lval) is true, return lval.
  4. Let rref be the result of evaluating LogicalANDExpression.
  5. 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
  • Thanks! Could there be a distinction between saying that a JavaScript expression is falsey and that it is false? – ppecher Sep 29 '11 at 20:14
  • 2
    @ppecher: "falsey" means a value that "acts like" `false` when a boolean value is expected. In other words anything that `ToBoolean` would convert to `false`. So, `""`, `0`, `null`, etc. are all "falsey". "false" means the actual boolean value, `false`. – Matthew Crumley Sep 29 '11 at 20:32
  • 1
    @ppecher: When you say "false", most people will think that it *is* a boolean (with a value of false). When you say "falsy", most people will understand that it is a value that, if converted to a boolean, would be false, but is not necessarily a boolean itself. – icktoofay Sep 29 '11 at 20:32
1

The operands are interpreted as booleans for evaluating the expression, but the return value of && or || is always one of the operands.

For example:

true && 0 === 0, not false
1 || false === 1, not true
Sjoerd
  • 74,049
  • 16
  • 131
  • 175
-1

Because JavaScript has an idea of truthiness that covers more than booleans.

Dave Newton
  • 158,873
  • 26
  • 254
  • 302