What Is ECMAScript | ES1 to ES2026 Explained
What is ECMAScript and how is it different from JavaScript? Learn the history of ES1, ES2, ES3, ES5, ES6, ES2016–ES2026 and the major features introduced in each version.
Muhammad Ali
Full Stack Developer
TechCamp Pro
What is ECMAScript and how is it different from JavaScript? Learn the history of ES1, ES2, ES3, ES5, ES6, ES2016–ES2026 and the major features introduced in each version.
Muhammad Ali
Full Stack Developer
ECMAScript is the standardized specification that defines the core JavaScript language.
Occasional notes on code, craft, and things I break along the way. No spam — unsubscribe anytime.
Written by
Muhammad Ali
Full Stack Developer
If you've worked with JavaScript, you've probably seen terms like:
ES5
ES6
ES2015
ES2020
ES2022
ES2025
But what exactly do they mean?
Are they different programming languages?
Is ECMAScript different from JavaScript?
And why do developers sometimes say ES6 and sometimes ES2015?
Let's start from the beginning.
ECMAScript is the standardized specification that defines the core JavaScript language.
JavaScript is the language developers commonly write, while ECMAScript is the standard that defines how that language behaves.
The standard is published as ECMA-262 and maintained by Ecma International's TC39 committee. ECMAScript was originally designed for web scripting but is now used as a general-purpose programming language across browsers, servers, and other environments. ([ECMA International][2])
This is one of the most common questions.
ECMAScript is the language specification/standard.
It defines things such as:
JavaScript is an implementation of the ECMAScript language used in real environments such as browsers and servers.
For example:
const message = "Hello";
console.log(message);
The syntax and behavior of const, strings, functions, objects, etc. are defined by ECMAScript.
The browser or runtime then provides additional capabilities such as:
document.querySelector();
fetch();
localStorage;
These are host/platform APIs, not simply the ECMAScript language itself.
This distinction is important: ECMAScript defines the core language, while environments such as browsers provide additional APIs around it. ([ECMA International][2])
JavaScript was created by Brendan Eich at Netscape and first appeared in Netscape Navigator.
As JavaScript became popular, standardization became necessary so different implementations could follow a common specification.
The first ECMAScript standard was adopted in June 1997. ([TC39][3])
The standard became known as:
ECMA-262
And the language specification became:
ECMAScript
You will often see:
ES5
ES6
ES2015
ES2020
ES2026
ES stands for ECMAScript.
For example:
ES5 → ECMAScript 5
ES6 → ECMAScript 6
ES2015 → ECMAScript 2015
Starting with ES2016, ECMAScript moved to a yearly release cycle.
That's why we have:
ES2016
ES2017
ES2018
ES2019
...
ES2026
rather than continuing with names like ES7, ES8, ES9, etc. ([TC39][3])
Here's the overall timeline:
| Version | Year | Common Name |
|---|---|---|
| ES1 | 1997 | ECMAScript 1 |
| ES2 | 1998 | ECMAScript 2 |
| ES3 | 1999 | ECMAScript 3 |
| ES4 | — | Never published |
| ES5 | 2009 | ECMAScript 5 |
| ES5.1 | 2011 | ECMAScript 5.1 |
| ES6 | 2015 | ECMAScript 2015 |
| ES2016 | 2016 | ES7 |
| ES2017 | 2017 | ES8 |
| ES2018 | 2018 | ES9 |
| ES2019 | 2019 | ES10 |
| ES2020 | 2020 | ES11 |
| ES2021 | 2021 | ES12 |
| ES2022 | 2022 | ES13 |
| ES2023 | 2023 | ES14 |
| ES2024 | 2024 | ES15 |
| ES2025 | 2025 | ES16 |
| ES2026 | 2026 | ES17 |
The official Ecma archive confirms the edition history from ES1 through ES2026. ([Ecma International][1])
ECMAScript 1 was the first official edition of the standard.
It was adopted in June 1997.
This established the foundation for the language that JavaScript implementations could follow. ([TC39][3])
At this point, ECMAScript was still a relatively young scripting language.
ES2 was released in 1998.
It mainly aligned ECMAScript with the corresponding international standard.
The changes were largely editorial rather than major language additions. ([TC39][3])
So ES2 isn't usually a version developers study for specific new JavaScript features.
ES3 was a much more important release.
It introduced improvements including:
try...catchFor example:
try {
throw new Error("Something went wrong");
} catch (error) {
console.log(error.message);
}
ES3 became extremely important as JavaScript grew alongside the web. ([TC39][3])
This is an interesting part of ECMAScript history.
There was significant work toward an ES4 specification.
However, the fourth edition was never completed or published as an official ECMAScript edition.
Some of the ideas and work from that effort influenced the development of ES6. ([Ecma International][1])
So:
ES1 → ES2 → ES3 → ❌ ES4 → ES5
There is no official published ECMAScript 4 standard.
ES5 was one of the most important releases before ES6.
It was published in 2009.
Some important additions and improvements included:
"use strict";
Strict mode enabled additional error checking and helped prevent certain problematic behaviors.
ES5 introduced important methods such as:
map()
filter()
reduce()
forEach()
some()
every()
Example:
const numbers = [1, 2, 3, 4];
const doubled = numbers.map(num => num * 2);
console.log(doubled);
Standardized JSON support became part of the language ecosystem:
JSON.parse();
JSON.stringify();
ES5 also added accessor properties and several object/property manipulation capabilities. ([TC39][3])
ES5.1 was a revision of ES5.
It mainly incorporated corrections and aligned the specification with the corresponding ISO standard.
It was adopted in June 2011. ([Ecma International][1])
Now we reach the most famous ECMAScript release:
ES6 is also called:
ECMAScript 2015
It was the 6th edition and was adopted in June 2015. ([TC39][3])
ES6 was a massive milestone for JavaScript.
It introduced many features that modern JavaScript developers use every day.
let and constBefore ES6:
var name = "Ali";
ES6 introduced:
let age = 25;
const name = "Ali";
This brought block-scoped variable declarations to JavaScript.
Before:
function add(a, b) {
return a + b;
}
ES6:
const add = (a, b) => a + b;
Arrow functions became one of the most commonly used modern JavaScript features.
Before:
const message = "Hello " + name;
ES6:
const message = `Hello ${name}`;
const user = {
name: "Ali",
age: 25
};
const { name, age } = user;
const first = [1, 2];
const second = [3, 4];
const numbers = [...first, ...second];
ES6 introduced class syntax:
class User {
constructor(name) {
this.name = name;
}
greet() {
return `Hello ${this.name}`;
}
}
ES6 introduced native Promises:
const promise = new Promise((resolve, reject) => {
resolve("Success");
});
Promises became a foundation for modern asynchronous JavaScript.
ES6 introduced native modules:
export function add(a, b) {
return a + b;
}
and:
import { add } from "./math.js";
ES6 introduced new collection types:
const users = new Map();
const uniqueNumbers = new Set();
This is directly related to our previous article on Map, Set, WeakMap, and WeakSet.
ES6 also introduced iterators and generators:
function* numbers() {
yield 1;
yield 2;
yield 3;
}
ES6's changes were so extensive that it became the foundation for the yearly incremental releases that followed. ([TC39][3])
If you've ever wondered why developers say:
"Modern JavaScript"
ES6 is a major reason.
ES6 changed JavaScript from a relatively limited scripting language into a much more powerful language for building large applications.
It introduced:
let / const
Arrow Functions
Classes
Modules
Promises
Map / Set
Destructuring
Spread
Rest Parameters
Generators
Iterators
And many more improvements.
After ES6, ECMAScript moved to an annual release cycle.
ES2016 introduced:
const result = 2 ** 3;
console.log(result); // 8
Array.prototype.includes()const numbers = [1, 2, 3];
console.log(numbers.includes(2)); // true
ES2016 was the first edition under the new yearly release process. ([TC39][3])
ES2017 introduced one of the most important features for modern asynchronous JavaScript:
async / awaitasync function getUser() {
const response = await fetch("/api/user");
return response.json();
}
It also introduced:
Object.values()Object.entries()Object.getOwnPropertyDescriptors()Async functions made Promise-based code significantly easier to read. ([TC39][3])
ES2018 introduced several useful features.
for await (const item of items) {
console.log(item);
}
const user = {
name: "Ali",
age: 25
};
const updatedUser = {
...user,
age: 26
};
It also introduced improvements to regular expressions, including named capture groups and Unicode property escapes. ([TC39][3])
ES2019 introduced two array methods that are especially useful:
flat()const numbers = [1, [2, 3], [4]];
console.log(numbers.flat());
Output:
[1, 2, 3, 4]
flatMap()const numbers = [1, 2, 3];
const result = numbers.flatMap(num => [num, num * 2]);
It also introduced:
Object.fromEntries();
and:
String.prototype.trimStart();
String.prototype.trimEnd();
([TC39][3])
ES2020 introduced several features that developers use constantly today.
user?.profile?.name;
const name = user.name ?? "Guest";
const bigNumber = 12345678901234567890n;
Promise.allSettled()Promise.allSettled(promises);
Other additions included:
globalThisPromise.allSettled()String.prototype.matchAll()import()import.meta([TC39][3])
ES2021 introduced:
String.prototype.replaceAll()const text = "hello hello";
console.log(text.replaceAll("hello", "hi"));
Promise.any()Promise.any(promises);
x ||= 10;
x &&= 20;
x ??= 30;
It also introduced:
AggregateErrorWeakRefFinalizationRegistryFor example:
const price = 1_000_000;
([TC39][3])
ES2022 introduced several important modern JavaScript features.
awaitconst data = await fetchData();
inside an appropriate module context.
class User {
#password;
constructor(password) {
this.#password = password;
}
}
It also introduced:
Object.hasOwn();
and:
array.at();
along with private methods, static class fields, static blocks, and other improvements. ([TC39][3])
ES2023 introduced several useful non-mutating array methods:
toSorted()
toReversed()
toSpliced()
with()
For example:
const numbers = [3, 1, 2];
const sorted = numbers.toSorted();
console.log(numbers);
console.log(sorted);
The original array remains unchanged.
ES2023 also added:
findLast()
findLastIndex()
and support for hashbang (#!) comments. ([TC39][3])
ES2024 introduced several advanced features.
Some notable additions included:
Object.groupBy()Object.groupBy(items, item => item.category);
Map.groupBy()Map.groupBy(items, item => item.category);
Promise.withResolvers()const {
promise,
resolve,
reject
} = Promise.withResolvers();
Other improvements included:
/v flagAtomics.waitAsync()String.prototype.isWellFormed()String.prototype.toWellFormed()([TC39][3])
ES2025 introduced several interesting additions.
IteratorA new global Iterator was introduced with static and prototype methods for working with iterators.
Set.prototype received methods for common set operations.
For example:
const a = new Set([1, 2, 3]);
const b = new Set([2, 3, 4]);
Modern Set operations make working with collections easier.
ES2025 also introduced:
RegExp.escape()
and:
Promise.try()
along with JSON module import support, import attributes, inline RegExp modifiers, and Float16Array support. ([TC39][4])
And now we reach the latest finalized ECMAScript version.
As of August 2026, ECMAScript 2026 is the 17th edition, finalized in June 2026. ([Ecma International][1])
Some notable ES2026 additions include:
Math.sumPrecise()Designed for summing an iterable of Numbers while reducing precision-loss problems associated with values of varying magnitude.
Math.sumPrecise(values);
Iterator.concat()Used to combine iterators sequentially.
Iterator.concat(iterator1, iterator2);
Array.fromAsync()Creates an Array from async iterables and other async sources.
const result = await Array.fromAsync(asyncItems);
Error.isError()Provides a way to identify Error objects.
Error.isError(value);
ES2026 adds methods to Map.prototype and WeakMap.prototype for retrieving a value with a default when a key isn't already present.
New Uint8Array methods support conversion to and from hexadecimal and Base64-encoded strings.
JSON.rawJSON()Provides more control over how raw JSON fragments are represented when using JSON.stringify().
These are among the additions included in the official ECMAScript 2026 specification. ([TC39][4])
This is where we need to be careful.
The current TC39 specification page is already showing a draft ECMAScript 2027 specification. ([TC39][5])
But:
ECMAScript 2027 is not the latest finalized standard yet.
For a production-focused article, we should therefore say:
Latest finalized version → ECMAScript 2026
Current upcoming draft → ECMAScript 2027
This distinction is important because the draft can continue to change before the next official edition is finalized.
Here's the evolution in a simpler format:
1997 → ES1
1998 → ES2
1999 → ES3
→ ES4 was never published
2009 → ES5
2011 → ES5.1
2015 → ES6 / ES2015
2016 → ES2016
2017 → ES2017
2018 → ES2018
2019 → ES2019
2020 → ES2020
2021 → ES2021
2022 → ES2022
2023 → ES2023
2024 → ES2024
2025 → ES2025
2026 → ES2026 ← Latest finalized
2027 → Draft
The yearly release model began with ES2016 and continues today. ([Ecma International][1])
A common misconception is:
"JavaScript is ES6."
That's not correct.
ES6 was one specific edition of ECMAScript.
Today, JavaScript continues to evolve:
ES6
↓
ES2016
↓
ES2017
↓
ES2018
↓
...
↓
ES2026
So when someone says "ES6 JavaScript", they usually mean the major generation of JavaScript introduced in 2015.
Modern JavaScript includes features introduced by many editions after ES6.
No.
You don't need to memorize every feature by release year.
Instead, focus on understanding modern JavaScript concepts:
let / constasync / awaitKnowing the history is useful because it helps you understand where JavaScript features came from and why the language evolved.
Understanding ECMAScript versions can help when:
You may encounter:
var
instead of:
let
const
Older projects may target ES5 or earlier syntax.
Interviewers may ask:
What was introduced in ES6?
or:
What is the difference between ES5 and ES6?
Different environments may support different language features depending on the runtime and tooling.
Knowing the history makes the evolution of JavaScript easier to understand.
This is one of the most common interview comparisons.
var name = "Ali";
var numbers = [1, 2, 3];
var doubled = numbers.map(function (number) {
return number * 2;
});
const name = "Ali";
const numbers = [1, 2, 3];
const doubled = numbers.map(number => number * 2);
ES6 made JavaScript syntax more expressive and introduced many features that became fundamental to modern development.
ECMAScript has come a long way since its first edition in 1997.
From the early days of ES1 and ES3 to the huge transformation introduced by ES6, JavaScript has continuously evolved to support increasingly complex applications.
The most important thing to remember is that ES6 was not the end of JavaScript's evolution.
It was the beginning of a modern, yearly release cycle:
ES6
↓
ES2016
↓
ES2017
↓
ES2018
↓
...
↓
ES2025
↓
ES2026
And JavaScript is still evolving.
As of August 2026, ECMAScript 2026 is the latest finalized standard, while work on the next edition continues through the TC39 process. ([Ecma International][1])