== (loose equality) compares values after converting them to a common type (coercion); === (strict equality) compares both value AND type with no conversion. Best practice is to use === almost always.
The == operator triggers the abstract equality algorithm, which coerces operands: numbers vs strings become numbers, booleans become numbers, and null == undefined is true (but neither equals anything else). This produces surprising results like 0 == '' (true), '' == false (true), and [] == ![] (true). === skips all coercion: if the types differ, it returns false immediately. Using === avoids an entire class of subtle bugs, which is why linters (eslint eqeqeq) enforce it. The one common, accepted use of == is x == null to check for null OR undefined in a single comparison.
Validating an API response field: if (response.count == '0') passes when count is the number 0 due to coercion, hiding a bug where the API returns a string instead of a number. Using === would catch the type mismatch and surface the contract violation.
Explain why [] == ![] evaluates to true in JavaScript.