ECMAScript is the standard that JavaScript implements, and since 2015 it has been released on a strict yearly schedule with editions named by their year. Knowing which edition introduced a feature tells you how widely it is supported and what transpile target you need. This reference lists every edition from ES5 to ES2025 with the major features each one shipped.
The edition timeline at a glance
| Edition | Year | Signature additions |
|---|---|---|
| ES5 | 2009 | Strict mode, Array.prototype.map/filter/reduce, native JSON |
| ES2015 (ES6) | 2015 | let/const, arrow functions, classes, promises, modules, Map/Set, generators |
| ES2016 | 2016 | Array.prototype.includes, exponentiation operator ** |
| ES2017 | 2017 | async/await, Object.values/entries, String.padStart/padEnd |
| ES2018 | 2018 | Async iteration, rest/spread for objects, Promise.finally |
| ES2019 | 2019 | Array.flat/flatMap, Object.fromEntries, optional catch binding |
| ES2020 | 2020 | BigInt, Promise.allSettled, nullish coalescing ??, optional chaining ?. |
| ES2021 | 2021 | String.replaceAll, Promise.any, logical assignment &&= ` |
| ES2022 | 2022 | Class fields and private methods, top-level await, Array.at, Object.hasOwn, Error.cause |
| ES2023 | 2023 | Array.findLast, toSorted/toReversed/toSpliced (non-mutating), Hashbang grammar |
| ES2024 | 2024 | Promise.withResolvers, Object.groupBy, ArrayBuffer.resize, RegExp v flag |
| ES2025 | 2025 | Iterator helpers, new Set methods (union, intersection, difference), Promise.try, RegExp.escape, Float16Array |
How the process works
The first edition most developers care about is ES5 (2009), which gave us strict mode, the functional array methods and native JSON. ES2015 (ES6) was the watershed release — block scoping, arrow functions, classes, promises, modules and the Map/Set collections all arrived at once. After ES2015, TC39 adopted a yearly cadence: each June a new edition ratifies whatever proposals have reached Stage 4, the final stage of the four-stage proposal process. That is why later editions are smaller and more focused, each adding a handful of well-defined features rather than a sweeping overhaul.
A proposal only enters the standard once it has two independent implementations and passes the official test262 conformance suite, so the year shown for each edition is the year those features became part of the language, not the year they first appeared behind a flag in a single engine.
Choosing a transpile target
Use the release year to choose a transpilation target. Tools like Babel and
TypeScript can down-level newer syntax (arrow functions, optional chaining)
for older runtimes, but features that need runtime support — such as BigInt,
WeakRef, the new Set methods, or Iterator.prototype.map — cannot be
polyfilled cleanly and require an engine new enough to implement them natively.
A practical approach: set your compile target to ES2020 for broad Node.js and
browser coverage, use @babel/preset-env with a browserslist to handle the
edge cases, and watch the stage-3 proposals currently in flight to anticipate what
will land in the next edition. Checking caniuse.com and node.green by feature
name is still the safest final verification before shipping.