These questions ask you to predict equality, truthiness, negation, and logical expressions. Work from the operator and operand types in that order; the spelling or everyday meaning of a value is not a coercion rule.
Use a short evaluation procedure
For ===, compare types first. Different types fail without conversion; object operands pass only when both references reach one object. Same-type numbers still have two special observations: NaN does not equal itself, while the two signed zeros compare equal. For ==, identify the actual type pair and apply its defined branch. It may convert, but it does not always turn both sides into strings or always turn both into numbers.
| Operation | Procedure and small example |
|---|---|
| Loose equality | Keep the pair visible. A boolean in a loose comparison becomes its numeric value; a string paired with a number is then converted numerically, with an empty string becoming zero. For example, "8" == 8 becomes a comparison of equal numbers and is true. Null has a narrow pairing with undefined and does not broadly match ordinary primitive values. |
| Boolean conversion | Check the fixed falsy set: false, both numeric zeros, 0n, the empty string, null, undefined, and NaN. Everything else in this topic is truthy; "no" and [] therefore both pass a condition. |
| Negation | Convert to boolean, then reverse it. One ! produces the opposite boolean; two !! operations return the original truthiness as a boolean rather than restoring the original value. |
| Logical AND | Read left to right. Return the first falsy operand, or the last operand if none is falsy; "go" && 12 returns 12. |
| Logical OR | Read left to right. Return the first truthy operand, or the last operand if none is truthy; "" || "fallback" returns the second string. |
The tempting wrong routes
- Treating === as a deep comparison makes similar-looking objects seem equal. Strict object equality asks about a shared reference, not matching properties or mutability.
- Reusing the Object.is rules for === reverses the two famous numeric special cases. Always identify which comparison operation is actually present.
- Reducing == to one slogan such as always stringify or always number-convert breaks on several type pairs. Follow each conversion required by the actual pair, then compare the resulting values.
- Making == and === agree for a string and a number skips the conversion performed by the loose comparison. Evaluate the loose branch before applying the no-conversion rule to the strict comparison.
- Treating an empty container like an empty string transfers a primitive rule to objects. Ordinary arrays and ordinary objects remain truthy even when they contain nothing.
- Reading a nonempty string by its message makes text such as "false" seem falsy. Boolean conversion checks whether the string is empty, not what its characters mean.
Try it
Which statement correctly compares loose and strict equality for both 0 and the empty string against false?
- Only the empty string is loosely equal to false
- Both are loosely equal but not strictly equal to false
- Both are strictly equal but not loosely equal to false
- Only zero is strictly equal to false
If value is the empty string, what is the result of !!value?
- false
- true
- the empty string
- undefined
What does the expression 0 || "ready" evaluate to?
- 0
- ready
- true
- false