Trace the fixed program
Compare three supplied pairs using === and ==. The console renders a and b as strings; the type table supplies the distinction those strings hide.
const cases=[[4,'4'],[4,4],[null,undefined]];
console.log(JSON.stringify(cases.map(([a,b])=>({a:String(a),b:String(b),strict:a===b,loose:a==b}))));
[{"a":"4","b":"4","strict":false,"loose":true},{"a":"4","b":"4","strict":true,"loose":true},{"a":"null","b":"undefined","strict":false,"loose":true}]| Original operands | typeof results | === / == |
|---|---|---|
| 4 / "4" | number / string | false / true |
| 4 / 4 | number / number | true / true |
| null / undefined | object / undefined | false / true |
Explain the result
The table reports typeof results. null is a primitive value of the Null type; typeof null returns "object" as a historical behavior, not a classification of null as an object. Strict equality rejects different types before comparing their values. Loose equality follows coercion rules, including the supplied null/undefined pair. Neither operator is an input-validation policy. NaN is not strictly equal to itself; separate objects are compared by identity.
Test the alternative
Converting both values to their displayed strings before comparing changes the question: two text representations can match while the original values do not. typeof null being object is a language quirk, not proof that null has properties.
console.log(JSON.stringify({rendered:String(4)===String('4'),original:4==='4',nullType:typeof null}));
{"rendered":true,"original":false,"nullType":"object"}Work the boundary case
Does === always give true when the operands have the same type?
Show the worked answer
No: 4===5 and NaN===NaN are false. Two independently created objects are also distinct references.
const object={};console.log(JSON.stringify({different:4===5,nan:NaN===NaN,separate:{}==={},same:object===object}));
{"different":false,"nan":false,"separate":false,"same":true}