3

Having the following test case: (find fiddle here)

var a = new Date();
var b = null;
var c = {test: "test"};

if(a)
    console.log(a); //--- prints the current date

if(b)
    console.log('null'); //--- never reached

if(c)
    console.log('test'); //--- prints 'test'

console.log(a && b); //--- prints null

Knowing that

console.log(typeof null); //--- prints "object"
console.log(typeof c); //--- prints "object"

I expect the result of

console.log(a && b); 

to be false and not null as it shown in the example.

Any hint?

BeNdErR
  • 17,471
  • 21
  • 72
  • 103

3 Answers3

4

From the MDN:

expr1 && expr2 : Returns expr1 if it can be converted to false; otherwise, returns expr2

new Date can't be converted to false (it's not falsy), so b is returned.

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • how do I know what can be converted to **false** and what can't? is there any table showing the types that can be converted to false? – BeNdErR Nov 09 '15 at 11:59
  • @BeNdErR: Values that coerce to false in conditions are called "falsey values." Here's the list: `null`, `undefined`, `0`, `""`, `NaN`, and of course, `false`. Everything else is *truthy*. So *all* non-`null` object references are truthy. – T.J. Crowder Nov 09 '15 at 12:00
  • @BeNdErR See the MDN (again) on "truthy": https://developer.mozilla.org/en-US/docs/Glossary/Truthy – Denys Séguret Nov 09 '15 at 12:01
  • There's also another answer on stackoverflow that provides the full falsey list: http://stackoverflow.com/questions/19839952/all-falsey-values-in-javascript – bug-a-lot Nov 09 '15 at 12:04
  • @BeNdErR Convert the expression to true/false by negating it and then use De-Morgan's law like `console.log(!(!a || !b));` or also `console.log(!!a && !!b)` should work – rajuGT Nov 09 '15 at 12:04
  • In addition to this: Since you use your `a && b` statement within a console.log(), it's return value get's casted to a `string`, not a `boolean`. Since `a && b` returns `null` (`b` being `null`), it get's casted to `"null"`. If you used the same statement in an `if statement`, the return value would get casted to a `boolean`, i.e. `false`. – Markai Nov 09 '15 at 12:05
3

I expect the result of

console.log(a && b);

to be false and not null as it shown in the example.

In many languages with && and || operators (or AND and OR), the result is always a boolean, yes.* But JavaScript's && and || are more useful than that: Their result is their left-hand operand's value or their right-hand operand's value, not coerced to boolean.

Here's how && works:

  1. Evaluate the left-hand operand.

  2. If the value is falsey (coerces to false when we make it a boolean), return the value (not the coerced value)

  3. If the value from #2 is truthy, evaluate and return the right-hand value (uncoerced)

The falsey values are null, undefined, 0, "", NaN, and of course, false. Everything else is truthy.

So for instance

console.log(0 && 'hi');    // 0

...shows 0 because 0 is falsey. Note it resulted in 0, not false. Similarly, the result here:

console.log(1 && 'hello'); // hello

...is 'hello' because the right-hand side isn't coerced at all by &&.

|| works similarly (I call it the curiously-powerful OR operator): It evaluates the left-hand side and, if that's truthy, takes that as its result; otherwise it evaluates the right-hand side and takes that as its result.

The only time you get true or false from && or || is if the selected operand is already a boolean.


* Of course, many (but not all) of those languages (Java, C#) also require that the operands to && and || already be booleans. C's an exception, it does some coercion, but still has the result of the operands as a boolean (or if you go back far enough, an int that will be 1 or 0).

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Either your writing is confusing or I'm more tired than I thought I am. What are the "many languages" where `new Date() && null` evaluates to `false` ? Do I misunderstand you ? – Denys Séguret Nov 09 '15 at 12:12
  • @DenysSéguret: In many languages, `&&` and `||` always result in a boolean. In most of those languages, of course, the operands to `&&` and `||` are required to be booleans, coercion isn't done (C#, Java, ...). C's an example where coercion is done (like JavaScript, though the rules are different), but the result is a boolean (unlike JavaScript). I'll reword that opening for greater clarity. – T.J. Crowder Nov 09 '15 at 12:15
0

From MDN:

Logical AND (&&) expr1 && expr2 Returns expr1 if it can be converted to false; otherwise, returns expr2. Thus, when used with Boolean values, && returns true if both operands are true; otherwise, returns false.

MDN Documentation

Taner
  • 31
  • 1
  • 2