What is type coercion, and when does JavaScript do it implicitly?
Type coercion is the engine converting a value from one type to another on its own. JavaScript is dynamically typed, so it will do this whenever an operator receives a type it cannot work with. The rule of thumb is that coercion happens with the arithmetic and string operators, and it does not happen with the strict equality operator.
console.log("5" + 3); // "53" - one operand is a string, so both become strings
console.log("5" - 3); // 2 - the minus sign only works on numbers
console.log("5" * "2"); // 10 - both operands are converted to numbers
console.log(true + 1); // 2 - true becomes 1
console.log(null + 1); // 1 - null becomes 0
console.log([] + {}); // "[object Object]" - both become stringsThe reason this surprises people is that the plus sign is doing double duty. The specification defines addition with a string operand as string concatenation, and addition with two non-string operands as numeric addition. Every other arithmetic operator is numeric only, so it converts its operands first.
Objects are harder. Before an operator runs, the engine converts its operands to primitives using the standard conversion protocol, which looks for a valueOf method first and then a toString method. Arrays inherit a toString that joins their elements with commas, which is why an empty array becomes an empty string and an array of numbers becomes a comma separated list.
Coercion is not a bug in the language so much as a consequence of a permissive design, but it is the single biggest source of surprising JavaScript bugs. The practical rule is to convert explicitly at the boundaries of your program, where data arrives from a form field, a query string or an API response, and trust the types everywhere else.