Accessing let/const bindings before initialization throws.
// console.log(x); // ReferenceError
let x = 1;Use try/catch/finally.
try {
JSON.parse("not json");
} catch (err) {
console.error("parse failed:", err.message);
} finally {
// cleanup
}Throw your own errors:
function mustBeNumber(x) {
if (typeof x !== "number") throw new TypeError("x must be a number");
return x;
}Shadowing is declaring a variable with the same name in an inner scope.
const x = 1;
{
const x = 2; // shadows outer x
console.log(x); // 2
}In JS, let/const cannot be shadowed by var in the same or nested scope in ways that break rules.
// This is illegal:
// let y = 1;
// {
// var y = 2; // SyntaxError
// }Coercion is implicit type conversion.
console.log("5" + 1); // "51" (string concatenation)
console.log("5" - 1); // 4 (numeric)
console.log(Boolean("")); // falsePrefer explicit conversions when clarity matters:
const n = Number("42");Common causes:
- keeping references in long-lived structures
- forgotten timers / intervals
- DOM references in browsers
// Browser example: keep references minimal and remove listeners.