Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemsJavaScript’s strangest-looking results usually follow a small set of rules: implicit type conversion, truthiness, equality, and the difference between declaring a variable and initializing it. Knowing which rule applies makes expressions easier to debug—and helps you write clearer checks.
1. Why does typeof null return "object"?
null is a primitive value, but typeof null returns "object". This is a longstanding compatibility quirk, not evidence that null is an object. For a direct null check, use strict equality:
As an Amazon Associate I earn from qualifying purchases.
if (value === null) {
// value is null
}
MDN explains the distinction in its JavaScript data types and data structures guide.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →2. Why is NaN a number that is unequal to itself?
NaN is a special numeric value, often produced when a numeric operation cannot yield a valid number. Its type is still number, but equality comparisons involving it are false—including comparison with itself:
#1 Best Overall
typeof NaN; // "number"
NaN === NaN; // false
Use Number.isNaN(value) to test specifically for it; equality is not a reliable NaN test. MDN covers NaN in its data types guide and describes the equality rules in Equality comparisons and sameness.
3. Why can + mean either concatenation or addition?
The plus operator depends on the operands after JavaScript converts them to primitives. If that conversion results in a string operand, + concatenates; otherwise, it performs numeric addition. Since the operations are evaluated left to right, changing the order changes the result:
"3" + 4 + 5; // "345"
// First: "3" + 4 → "34"; then: "34" + 5 → "345"
3 + 4 + "5"; // "75"
// First: 3 + 4 → 7; then: 7 + "5" → "75"
When an expression mixes strings and numbers, make the intended conversion explicit or split the work into named steps. MDN explains the operator and conversion behavior in its data types guide and JavaScript language overview.
4. Why can == treat different types as equal?
Loose equality applies a set of conversion rules before comparing some values. For example, the Boolean in 1 == true is converted to a number, making the comparison equivalent to 1 == 1. Strict equality does not equate values of different types:
Rank #2
1 == true; // true
1 === true; // false
The loose-equality algorithm has special cases for nullish values, strings, BigInts, and objects; it does not simply convert every value to a number. For ordinary comparisons, === is usually easier to reason about because it avoids these implicit conversions. See MDN’s equality guide and language overview.
5. Why are empty arrays and objects truthy?
JavaScript’s truthiness rule does not treat “empty” as false. An empty array or object is truthy, so each enters the if block:
if ([]) {
// runs
}
if ({}) {
// also runs
}
The falsy values are false, 0, -0, 0n, "", NaN, null, and undefined. Other values are truthy. To check whether an array is empty, test its length instead:
Free tools Windows power users keep installed
One-click scans. No signup required.
if (items.length === 0) {
// items is empty
}
MDN lists these rules in its JavaScript language overview.
6. Why do && and || return values instead of Booleans?
Logical operators short-circuit based on truthiness, but return one of their operands—not a normalized true or false. For &&, JavaScript returns the first falsy operand, or the last operand if all are truthy. For ||, it returns the first truthy operand, or the last operand if none is truthy:
0 && "ready"; // 0
"ready" && "next"; // "next"
"" || "fallback"; // "fallback"
"ready" || "fallback"; // "ready"
This behavior supports idioms such as value && value.property, but optional chaining is often clearer when the intent is to access a property only if a value is not nullish:
value?.property
The operator return rules are described in MDN’s language overview.
7. Why can a var declared inside a block be used outside it?
var is scoped to its containing function, or to the global scope when declared outside a function. An if block does not create a scope for a var binding:
Rank #4
if (true) {
var message = "available";
}
console.log(message); // "available"
By contrast, let and const are block scoped. If a value should exist only inside a block, use one of those declarations. MDN outlines these distinctions in its grammar and types guide.
8. What does hoisting actually mean?
“Hoisting” is a shorthand for how declarations are available within their scope; JavaScript does not literally move source lines. The outcome depends on the declaration type:
var: binding available as undefined
A var binding is initialized to undefined before its assignment runs. Reading it earlier does not retrieve the later assigned value:
console.log(count); // undefined
var count = 3;
let and const: temporal dead zone
These bindings exist in their scope but cannot be accessed before execution reaches their declaration. Accessing one too early throws a ReferenceError:
Best Value
console.log(total); // ReferenceError
let total = 3;
Function declarations: available earlier in scope
A function declaration can be called before its position in the source code:
greet(); // "hello"
function greet() {
return "hello";
}
MDN discusses scope, initialization, and function declarations in its grammar and types guide.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.9. Why does document.all behave like undefined in some checks?
document.all is a browser-specific, legacy compatibility exception. The HTML platform gives this host-defined object special behavior in selected operations: it is falsy, loosely equal to null or undefined, and has the typeof result "undefined". Those behaviors do not make it an ordinary undefined value or establish a general rule for objects.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →typeof document.all; // "undefined"
Boolean(document.all); // false
document.all == null; // true
This exception is documented in MDN’s equality guide and specified in ECMA-262, 12th edition, Annex B.3.7.
10. How can objects and arrays change an expression through conversion?
When an operation needs a primitive value from an object, JavaScript may consult the object’s [Symbol.toPrimitive] method, then its valueOf and toString methods according to the conversion rules. The resulting primitive can affect concatenation or equality. For instance, in an expression context, an ordinary object and an empty array can produce a string:
({} + []); // "[object Object]"
The parentheses make the expression context clear: a brace at the start of a statement can instead be parsed as a block, so brace-leading examples can behave differently depending on where they appear. When an expression’s result looks surprising, identify the conversion the operator requests and the primitive each operand supplies. MDN explains object-to-primitive conversion in its data types and data structures guide.
Quick Recap
A practical way to debug a surprising expression
- Write down each operand’s type before evaluating the operator.
- Check whether the operator converts values, and whether evaluation order changes what gets converted next.
- For a condition, distinguish truthiness from checks such as “is null” or “is an empty array.”
- For variables, identify the declaration type and scope before assuming a value is available.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
Recommended Free Tools




