01What the language gave you, and what you should actually use

Douglas Crockford's original "good parts" thesis — that JavaScript hid a genuinely powerful language inside a mess of bad decisions — still holds. But the mess has shrunk. ES2015 and the decade of incremental additions that followed gave us enough to retire a lot of the old workarounds permanently.

The parts worth reaching for daily: const and let over var (block scoping eliminates a whole class of subtle bugs), arrow functions for callbacks and lexical this, destructuring for extracting values cleanly, template literals instead of string concatenation, optional chaining (?.) and nullish coalescing (??) for safely navigating uncertain data. These aren't novelties — they're the language now. Async/await, built on Promises, makes asynchronous code readable enough that callback pyramids have no excuse left.

Array methods — map, filter, reduce, flatMap, find, some, every — deserve genuine fluency. They're not functional programming cosplay; they're the clearest way to express intent on collections. Alongside them, Set and Map are underused. If you're still reaching for an object as a makeshift dictionary or a manual deduplication loop, reach further.

Array methods — map , filter , reduce , flatMap , find , some , every — deserve genuine fluency.

02What to retire, and what's still sharp enough to cut you

Stop writing var. Stop using arguments — rest parameters (...args) do the job with an actual array. Stop manually binding this where an arrow function or a class method suffices. And if you're still reaching for == over ===, stop.

The sharp edges that remain are real. this binding in regular functions still bites in callbacks and event handlers — the rule has never changed, only the ease of avoiding the problem. Type coercion is still quiet and weird: [] + {} is "[object Object]", and {} + [] can be 0 depending on context. The prototype chain still exists whether you use class syntax or not — class is syntax sugar, not a new object model. And NaN !== NaN is still true, which is why Number.isNaN() exists.