A Brief History of ECMAScript Versions in JavaScript
Introduction
As a programming language, JavaScript is widely used in web development for creating interactive and dynamic user interfaces. It was created by Brendan Eich in 1995 under the name Mocha, which was later changed to LiveScript, and finally to JavaScript.
The ECMAScript standard is developed and maintained by Ecma International, a Swiss-based standards organization, and it is officially designated as ECMA-262. This standard serves as the foundation of JavaScript, and its versions directly influence the development and evolution of the language. In this article, we'll provide an overview of the ECMAScript evolution, offering insights into some of the key updates in each version.
ECMAScript 1 (1997)
ECMAScript 1, also known as ES1, was the first version of the ECMAScript standard and was released in 1997. It was based on the JavaScript language and included features such as variables, functions, and basic control flow statements.
// Example of a variable in ES1
var name = "John Doe";
console.log(name); // Output: "John Doe"
// Example of a function in ES1
function add(a, b) {
return a + b;
}
console.log(add(1, 2)); // Output: 3
ECMAScript 2 (1998)
ECMAScript 2, also known as ES2, was the second version of the ECMAScript standard and was released in 1998. It made minor changes to the language and mainly focused on making the standard more consistent.
ECMAScript 3 (1999)
ECMAScript 3, also known as ES3, was the third version of the ECMAScript standard and was released in 1999. It introduced several important features such as regular expressions, try-catch statements, and improved string handling.
// Example of regular expressions in ES3
var text = "Hello, World!";
var regex = /Hello/;
console.log(regex.test(text)); // Output: true
// Example of try-catch statement in ES3
try {
var x = y + 1;
} catch (error) {
console.log(error); // Output: ReferenceError: y is not defined
}
ECMAScript 4 (Never Released)
ECMAScript 4 was planned to be the fourth version of the ECMAScript standard, but it was never released. It was intended to introduce significant changes to the language, including classes, interfaces, and namespaces. However, the proposal faced significant opposition, and the development was ultimately abandoned.
ECMAScript 5 (2009)
ECMAScript 5, also known as ES5, was the fifth version of the ECMAScript standard and was released in 2009. It introduced several important features such as strict mode, JSON support, and improved array manipulation.
// Example of strict mode in ES5
function add(a, b) {
"use strict";
return a + b;
}
console.log(add(1, 2)); // Output: 3
// Example of JSON support in ES5
var jsonText = '{"name":"John Doe","age":30}';
var jsonData = JSON.parse(jsonText);
console.log(jsonData.name); // Output: "John Doe"
// Example of improved array manipulation in ES5
var numbers = [1, 2, 3, 4, 5];
console.log(numbers.indexOf(3)); // Output: 2
console.log(numbers.map(function(number) { return number * 2; })); // Output: [2, 4, 6, 8, 10]
ECMAScript 5.1 (2011)
ECMAScript 5.1, also known as ES5.1, was a minor update to ECMAScript 5 and was released in 2011. It mostly focused on making the standard more consistent and correcting errors.
ECMAScript 6 (2015)
ECMAScript 6, also known as ES6, was the sixth version of the ECMAScript standard and was released in 2015. It introduced several important features such as let
and const
, arrow functions, template literals, and classes.
// Example of let and const in ES6
let name = "John Doe";
const age = 30;
// Example of arrow function in ES6
let add = (a, b) => a + b;
console.log(add(1, 2)); // Output: 3
// Example of template literals in ES6
let message = `Hello, ${name}!`;
console.log(message); // Output: "Hello, John Doe!"
// Example of class in ES6
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
return `Hello, ${this.name}!`;
}
}
let john = new Person("John Doe", 30);
console.log(john.greet()); // Output: "Hello, John Doe!"
You can learn more about ES6 in our ES6 JavaScript article, as well as separate breakdowns of:
- Arrow Functions
- Classes
- Default Parameters
- Destructuring
- Let and Const
- Maps
- Sets
- Template Literals
These can be found on the left side of the navigation under the ES6 section.
ECMAScript 2016 (ES7)
ECMAScript 2016, also known as ES7, was the seventh version of the ECMAScript standard and was released in 2016. It introduced two main features: the exponentiation operator and Array.prototype.includes()
.
// Example of exponentiation operator in ES7
let square = 2**2;
console.log(square); // Output: 4
// Example of Array.prototype.includes in ES7
let numbers = [1, 2, 3, 4, 5];
console.log(numbers.includes(3)); // Output: true
ECMAScript 2017 (ES8)
ECMAScript 2017, also known as ES8, was the eighth version of the ECMAScript standard and was released in 2017. It introduced several new features, including async/await, Object.values()
, Object.entries()
, and string padding.
// Example of async/await in ES8
async function fetchData() {
let response = await fetch('https://api.example.com/data');
let data = await response.json();
return data;
}
// Example of Object.values() and Object.entries() in ES8
let person = { name: "John Doe", age: 30 };
console.log(Object.values(person)); // Output: ["John Doe", 30]
console.log(Object.entries(person)); // Output: [["name", "John Doe"], ["age", 30]]
// Example of string padding in ES8
let text = "Hello";
console.log(text.padStart(10, '-')); // Output: "-----Hello"
console.log(text.padEnd(10, '-')); // Output: "Hello-----"
ECMAScript 2018 (ES9)
ECMAScript 2018, also known as ES9, brought significant updates such as asynchronous iteration, Promise.prototype.finally()
, and rest/spread operators.
// Example of asynchronous iteration in ES9
async function asyncIterable() {
let iterable = {
[Symbol.asyncIterator]() {
let i = 0;
return {
next() {
if (i < 3) {
return Promise.resolve({ value: i++, done: false });
}
return Promise.resolve({ done: true });
}
};
}
};
for await (let value of iterable) {
console.log(value); // Output: 0, 1, 2
}
}
// Example of Promise.prototype.finally() in ES9
fetch('https://api.example.com/data')
.then(data => console.log(data))
.catch(error => console.log(error))
.finally(() => console.log('Finished!'));
// Example of rest/spread operators in ES9
let person = { name: "John Doe", age: 30, country: "USA" };
let {name, ...rest} = person;
console.log(name); // Output: "John Doe"
console.log(rest); // Output: { age: 30, country: "USA" }
ECMAScript 2019 (ES10)
ECMAScript 2019, also known as ES10, introduced features like Array.prototype.flat()
, Array.prototype.flatMap()
, and Object.fromEntries()
.
// Example of Array.prototype.flat() and Array.prototype.flatMap() in ES10
let array = [1, 2, [3, 4]];
console.log(array.flat()); // Output: [1, 2, 3, 4]
let numbers = [1, 2, 3, 4];
console.log(numbers.flatMap(x => [x, x*2])); // Output: [1, 2, 2, 4, 3, 6, 4, 8]
// Example of Object.fromEntries() in ES10
let entries = [['name', 'John Doe'], ['age', 30]];
console.log(Object.fromEntries(entries)); // Output: { name: "John Doe", age: 30 }
ECMAScript 2020 (ES11)
ECMAScript 2020, also known as ES11, came with features such as BigInt for larger integers, Promise.allSettled()
, Nullish Coalescing Operator (??
), and Optional Chaining (?.
).
// Example of globalThis in ES11
console.log(globalThis); // Output: Window {...}
// Example of private fields in ES11
class Person {
#name = "John Doe";
#age = 30;
getName() {
return this.#name;
}
getAge() {
return this.#age;
}
}
let person = new Person();
console.log(person.getName()); // Output: "John Doe"
console.log(person.getAge()); // Output: 30
// Example of nullish coalescing in ES11
let value = null;
console.log(value ?? "default"); // Output: "default"
ECMAScript 2021 (ES12)
ECMAScript 2021, also known as ES12, introduced several new features such as additional logical assignment operators, numeric separators, Promise.any()
, and String.prototype.replaceAll()
.
// Example of Logical Assignment Operators in ES12
let a = 0, b = 1;
a &&= b;
console.log(a); // Output: 0
a ||= b;
console.log(a); // Output: 1
a &&= b;
console.log(a); // Output: 1
// Example of Numeric Separators in ES12
let billion = 1_000_000_000; // This is equivalent to let billion = 1000000000;
console.log(billion); // Output: 1000000000
// Example of Promise.any() in ES12
let promises = [
Promise.reject('1'),
Promise.resolve('2'),
Promise.reject('3')
];
Promise.any(promises)
.then(value => console.log(value)) // Output: "2"
.catch(error => console.log(error));
// Example of String.prototype.replaceAll() in ES12
let string = "foo foo foo";
console.log(string.replaceAll("foo", "bar")); // Output: "bar bar bar"
ECMAScript 2022 (ES13)
ECMAScript 2022 (ES13) is the 13th edition of the ECMAScript standard that preceded the current ECMAScript 2023 (ES14). It introduced several significant new features:
The ability to use top-level
await
, making it possible to use the keyword outside of an async functionNew class elements: private and public instance fields, private and public static fields, private instance methods and accessors, and private static methods and accessors
The ability to use static blocks inside classes, which allows for per-class evaluation initialization
The
#x in obj
syntax which allows you to test for the presence of private fields on objectsRegular expression match indices via the
/d
flag, which provides start and end - indices for matched substringsThe
cause
property onError
objects, that can be used to record a causation chain in errorsThe at method for Strings, Arrays, and TypedArrays, which allows relative indexing
Object.hasOwn
, a convenient alternative toObject.prototype.hasOwnProperty
You can check out some elaborate examples of these concepts here.
ECMAScript 2023 (ES14)
The 14th edition of the ECMAScript standard, ECMAScript 2023, introduced several new methods on Array.prototype
and TypedArray.prototype
, including toSorted
, toReversed
, with
, findLast
, and findLastIndex
. Additionally, the toSpliced
method was added to Array.prototype
.
This version began supporting "#!"
comments at the start of files, paving the way for directly executable ECMAScript files. Furthermore, it permitted the use of most Symbols as keys in weak collections. These new features potentially offer developers improvements in several areas such as array handling, symbol usage in weak maps, script executability, and functional programming with a stronger emphasis on immutability.
Here's a quick rundown of these features:
Reverse Array Search: The
findLast()
andfindLastIndex()
methods were introduced toArray
andTypedArray
prototypes. These methods, akin tofind()
andfindIndex()
, operate in reverse order, offering a straightforward approach to searching an array from the end without needing a temporary array duplicate or complex index calculations.Flexible Key Usage in WeakMaps: This update allows non-registered Symbols to be used as keys in a
WeakMap
, providing more options for developers to use symbols as unique identifiers for data storage and retrieval.Executable Script Support: The standardization of hashbangs (or shebangs) in executable scripts now enables ECMAScript files to be run directly from the command line, potentially improving script portability across various operating systems.
Immutable Array Operations: Newly introduced equivalents of
reverse()
,sort()
, andsplice()
methods onArray.prototype
, return a new array copy instead of altering the original array. Alongside thewith()
method, this supports a functional programming style where data immutability is often emphasized. Below, you can observe illustrative examples of some of the methods:- The
toSorted()
method is likesort()
, but it returns a new sorted array, leaving the original array unchanged.
let arr = [3, 1, 2]; let sortedArr = arr.toSorted(); console.log(sortedArr); // Output: [1, 2, 3] console.log(arr); // Output: [3, 1, 2]
- The
with()
method allows modifying a single element based on its index and returning a new array.
let arr2 = ['apple', 'banana', 'cherry']; let newArr2 = arr2.with(1, 'blueberry'); console.log(newArr2); // Output: ['apple', 'blueberry', 'cherry'] console.log(arr2); // Output: ['apple', 'banana', 'cherry']
- The
You can access the complete specification in the latest draft here.
Understanding ECMAScript Proposals
The development of ECMAScript specifications is overseen by the Ecma TC39 committee, following a structured process to evolve new proposals from initial ideas to fully specified, tested, and implemented features. Proposals move from an introductory stage (Strawperson), through stages of drafting, candidacy, and finalization. Champions guide proposals through these stages, with the committee's consensus required for stage advancements.
The process is transparent and provides opportunities for input from both committee members and the broader community, culminating in the integration of finished proposals into new revisions of the ECMAScript standard.
Detailed insights into this process can be found in the official process document.
Conclusion
As we already saw, the development of new specifications involves a rigorous process of testing and validation to ensure their accuracy, feasibility, and compatibility with existing web applications. Each advancement, such as those in ECMAScript 2023 (ES14), plays a role in shaping the landscape of JavaScript, making it more robust and dynamic in the face of changing digital demands.
At Web Reference, we strive to stay attuned to the continuous evolution of the JavaScript ecosystem, numerous programming languages, web technologies, and essential design aspects. As part of this effort, we have curated a range of resources. One such resource is our Introduction to JavaScript, which serves as a starting point for the language's extensive key facets and crucial concepts.