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:
Evaluate the left-hand operand.
 
If the value is falsey (coerces to false when we make it a boolean), return the value (not the coerced value)
 
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).