== evaluates the spec operation IsLooselyEqual(x, y), which tries rules in order and stops at the first that applies:
- Same type → compare as
===does (soNaN == NaNisfalse). nullandundefinedare equal to each other, and to nothing else.- Number and String → convert the string with
ToNumber, then compare again. - BigInt and String → parse the string as a BigInt; if it is not a valid BigInt literal, the result is
false. - Boolean on either side → convert it to a Number (
true→1,false→0), then compare again. - Object vs String, Number, BigInt or Symbol → convert the object with
ToPrimitive(no hint, sovalueOffirst for ordinary objects), then compare again. - BigInt and Number → equal if they represent the same mathematical value.
- Anything else →
false.
Each conversion step returns to the top of the algorithm, so one comparison can convert several times: "1" == true becomes "1" == 1, then 1 == 1.
Notable consequences: null == 0 is false (rule 2 consumes null before any numeric conversion), NaN is never equal to anything, and two objects compare by identity because they have the same type. Not transitive: "0" == 0 and 0 == "" are true, but "0" == "" is false (same type, so strict string comparison).
Default to ===. The widely accepted exception is x == null, which tests for null or undefined in one check.