As programming languages go, JavaScript’s development has been positively frantic in the last few years. With each year now seeing a new release of the ECMAScript specification, it’s easy to get confused about JavaScript versioning, which version supports what, and how you can future-proof your code.
To better understand the how and why behind this seemingly constant stream of new features, let’s take a brief look at the history of the JavaScript and JavaScript versioning, and find out why the standardization process is so important.
Key Takeaways
- ES6 (also known as ES2015) marked a significant shift in JavaScript versioning, introducing features like classes, promises, arrow functions, ES modules, generators, and iterators. This was a large foundational update supporting future, smaller, annual JavaScript versioning.
- The TC39 process, a proposal-based model for discussing and adopting elements, was established with ES2015. This process involves five stages: Strawman, Proposal, Draft, Candidate, and Finished, each progressively formalizing and implementing the proposed feature.
- Following ES2015, subsequent releases have occurred each June, with ES2016 (ES7) and ES2017 (ES8) introducing incremental features and improvements. ES2018 introduced a small set of powerful additions such as asynchronous iterators and object spread and rest properties.
- The renaming of ES6 to ES2015 was done to reflect the year of its release and to move away from version numbers. This was done to avoid confusion and to indicate that JavaScript is a living language, continually updated and improved. The new naming convention also helps to indicate the regularity of updates and improvements to the language.
The Early History of JavaScript Versioning
The prototype of JavaScript was written in just ten days in May 1995 by Brendan Eich. He was initially recruited to implement a Scheme runtime for Netscape Navigator, but the management team pushed for a C-style language that would complement the then recently released Java.
JavaScript made its debut in version 2 of Netscape Navigator in December 1995. The following year, Microsoft reverse-engineered JavaScript to create their own version, calling it JScript. JScript shipped with version 3 of the Internet Explorer browser, and was almost identical to JavaScript — even including all the same bugs and quirks — but it did have some extra Internet Explorer-only features.
The Birth of ECMAScript
The necessity of ensuring that JScript (and any other variants) remained compatible with JavaScript motivated Netscape and Sun Microsystems to standardize the language. They did this with the help of the European Computer Manufacturers Association, who would host the standard. The standardized language was called ECMAScript to avoid infringing on Sun’s Java trademark — a move that caused a fair deal of confusion. Eventually ECMAScript was used to refer to the specification, and JavaScript was (and still is) used to refer to the language itself.
The working group in charge of JavaScript versioning and maintaining ECMAScript is known as Technical Committee 39, or TC39. It’s made up of representatives from all the major browser vendors such as Apple, Google, Microsoft and Mozilla, as well as invited experts and delegates from other companies with an interest in the development of the Web. They have regular meetings to decide on how the language will develop.
When JavaScript was standardized by TC39 in 1997, the specification was known as ECMAScript version 1. Subsequent versions of ECMAScript were initially released on an annual basis, but ultimately became sporadic due to the lack of consensus and the unmanageably large feature set surrounding ECMAScript 4. This version was thus terminated and downsized into 3.1, but wasn’t finalized under that moniker, instead eventually evolving into ECMAScript 5. This was released in December 2009, 10 years after ECMAScript 3, and introduced a JSON serialization API, Function.prototype.bind, and strict mode, amongst other capabilities. A maintenance release to clarify some of the ambiguity of the latest iteration, 5.1, was released two years later.
Do you want to dive deeper into the history of JavaScript? Then check out chapter one of JavaScript: Novice to Ninja, 2nd Edition.
ECMAScript 2015 and the Resurgence of Yearly Releases
With the resolution of TC39’s disagreement resulting from ECMAScript 4, Brendan Eich stressed the need for nearer-term, smaller releases. The first of these new specifications was ES2015 (originally named ECMAScript 6, or ES6). This edition was a large but necessary foundation to support the future, annual JavaScript versioning. It includes many features that are well-loved by many developers today, such as:
ES2015 was the first offering to follow the TC39 process, a proposal-based model for discussing and adopting elements.
The TC39 Process
There are five stages through which a proposal must pass before it can be accepted into an upcoming version of ECMAScript.
Stage 0: Strawman
This is a convenience step to permit the submission of ideas to the specification. Features can be suggested by anyone — namely, TC39 members and non-members who have registered as a contributor.
Stage 1: Proposal
The first stage at which a proposal is formalized. It’s necessary that:
- any existing problems rectified by the solution are described
- an API outline is provided, alongside high-level implementation details, as well as polyfills and/or demos
- potential impediments are discussed upfront.
A champion must be selected to adopt and advance the proposal. This individual must be a TC39 member.
Stage 2: Draft
This is the milestone at which a feature is likely to be included in a future version of ECMAScript. Here, the proposal’s syntax and semantics are detailed using the formal language described by the specification. An experimental implementation should be available at this point.
Stage 3: Candidate
Here, the majority of the proposal and the backing technology have been developed, but it requires further feedback from users and implementers (such as browser vendors). Once this is available and acted upon, the outline and specification details are finalized and signed off by designated reviewers and the appointed editor. As a compliant implementation is required at this stage, only critical changes are henceforth embraced.
Stage 4: Finished
The proposal has been accepted and can be added to ECMAScript. It’s thus inherent that:
- acceptance tests, which are part of the Test262 suite and are crafted with JavaScript, have been written to prove the conformity and behavior of the feature
- at least two compliant implementations are available, and have shipped, all of which demonstrate robustness and developer usability
- a pull request has been submitted to the official ECMA-262 repo, which has been signed off by the specification editor.
The above repository’s contribution document further details the use of GitHub issues and pull requests for managing additions to the language.
Moving Forward
Following the completion of ES2015 and the establishment of the TC39 process of JavaScript versioning and updating, subsequent releases have occurred each June, with the inclusion of proposals being timeboxed to one year. At the time of writing, there have been three new specifications.
ES2016
Also known as ES7, this was the first smaller, incremental version of ECMAScript. Aside from bug fixes, it added just two features.
Array.prototype.includes
This instance method simplifies searching for values in an Array
:
// pre-ES2016:
const hasBob = names.indexOf('bob') > -1;
// ES2016:
const hasBob = names.includes('bob');
Exponent Operator
Prior to ES2016, one could perform exponentiation with Math.pow(base, exponent)
. This version introduces an operator (**) that has its own precedence:
// pre-ES2016
Math.pow(5, 3); // => 125
// ES2016
5 ** 3; // => 125
ES2017
A slightly larger release, ES2017 (aka ES8) contains a handful of useful methods and syntactical constructs.
Asynchronous Functions
Promises have saved us from callback hell, but their API nonetheless demonstrates verbosity. Asynchronous functions abstract them with a syntax that closely resembles synchronous code:
// promises
const getProfile = name => {
return fetch(`https://some-api/people/${name}`)
.then(res => res.json())
.then(({ profile }) => profile); // destructuring `profile` from parsed object
};
// async/await
const getProfile = async name => {
const res = await fetch(`https://some-api/people/${name}`);
const { profile } = await res.json();
return profile;
};
String Padding Methods
String.prototype.padStart(length, padder) and padEnd(length, padder) will respectively prepend and append padder
(this is optional, defaulting to a space) to a string repeatedly until it reaches length
characters:
'foo'.padStart(6); // => ' foo';
'foo'.padEnd(6); // => 'foo ';
'foo'.padStart(10, 'bar'); // => 'barbarbfoo';
'foo'.padEnd(10, 'bar'); // => 'foobarbarb';
Other features include trailing commas, shared memory and atomics, and static Object
methods (Object.entries(), Object.values(), and Object.getOwnPropertyDescriptors().)
If you’d like to read more about the complete feature set of ES2017, please see our article covering what’s new in ES2017.
ES2018
This latest iteration, at the time of writing, introduces a small set of powerful additions.
Asynchronous Iterators
While Promise.all()
allows you to await the resolution of multiple promises, there are cases in which you may need to sequentially iterate over asynchronously-retrieved values. It’s now possible to await async iterators along with arrays of promises:
(async () => {
const personRequests = ['bob', 'sarah', 'laura'].map(
n => fetch(`https://api/people/${n}`)
);
for await (const response of personRequests) {
console.log(await response.json());
}
})();
Object Spread and Rest Properties
Ostensibly, these two syntactical improvements are already popular amongst JavaScript developers thanks to the availability of compilers such as Babel. Object spread and rest properties are similar to array spread and rest properties, and permit the shallow copying and grouped destructuring of object properties:
const react = {
name: 'React',
vendor: 'Facebook',
description: 'A JavaScript library for building user interfaces',
npm: true,
cdn: true,
};
/* Use spread syntax inside an object literal to create
* a shallow copy, while overriding certain properties.
*/
const vue = {
...react,
vendor: 'Evan You',
description: 'A JavaScript framework for building UIs',
};
/* Use rest within destructuring syntax to create a
* label for accessing additional object properties.
*/
const { name, vendor, ...rest } = vue;
console.log(rest.description); // => 'A JavaScript framework for building UIs'
Other accepted proposals are Promise.prototype.finally(), as well as enhancements to regular expressions and template literals.
If you’d like to read more about the complete feature set of ES2018, please see our article covering what’s new in ES2018.
A Final Word
JavaScript has evolved greatly over a short space of time. While this is attributable to the ECMAScript standard and the brilliant work of TC39, it was initially an arduous journey due to the previous lack of stability and cohesion in JavaScript versioning and development.
Thanks to the relatively mature proposals process, the language can only improve in a pragmatic and manageable manner. It’s a great time to be a web developer!
Frequently Asked Questions (FAQs) about JavaScript Versioning: ES6 and ES2015
What is the main difference between ES6 and ES2015?
ES6 and ES2015 are essentially the same thing. ES6 is the sixth edition of the ECMAScript programming language, which is standardized by ECMA International. ES2015 is simply the new name for ES6, reflecting the year it was released. The renaming was done to indicate the year of release and to move away from version numbers, which could be confusing.
Why was ES6 renamed to ES2015?
The renaming of ES6 to ES2015 was done to reflect the year of its release and to move away from version numbers. This was done to avoid confusion and to indicate that JavaScript is a living language, continually updated and improved. The new naming convention also helps to indicate the regularity of updates and improvements to the language.
What are the key features introduced in ES6/ES2015?
ES6/ES2015 introduced several new features to JavaScript, including let and const for variable declarations, arrow functions for shorter function syntax, template literals for string interpolation, classes for object-oriented programming, promises for asynchronous programming, and modules for code organization, among others.
How does ES6/ES2015 improve JavaScript coding?
ES6/ES2015 improves JavaScript coding in several ways. It introduces new syntax and features that make the language more powerful and easier to use. For example, arrow functions provide a more concise syntax for writing functions, while promises make it easier to handle asynchronous operations. The introduction of modules also helps to organize code better, making it easier to manage and maintain.
How can I start using ES6/ES2015 features in my JavaScript code?
To start using ES6/ES2015 features in your JavaScript code, you can use a transpiler like Babel, which converts ES6 code into ES5 code that can be run in current browsers. You can also use a module bundler like Webpack to manage and bundle your JavaScript modules.
Are there any compatibility issues with ES6/ES2015?
While most modern browsers support the majority of ES6/ES2015 features, there may be some compatibility issues with older browsers. To ensure compatibility, you can use a polyfill, which provides the functionality that you expect the browser to natively support.
What is the difference between JavaScript and ECMAScript?
JavaScript is a programming language that was initially developed by Netscape. ECMAScript is the standardized version of JavaScript, developed by ECMA International. JavaScript implements ECMAScript, meaning that it follows the rules and structures defined in the ECMAScript standard.
What is the future of JavaScript after ES6/ES2015?
After ES6/ES2015, JavaScript continues to evolve with new versions released every year, each introducing new features and improvements. The future of JavaScript is likely to see more powerful features, better performance, and increased compatibility across different platforms and devices.
How does TypeScript relate to ES6/ES2015?
TypeScript is a superset of JavaScript that adds static types to the language. It supports all the features of ES6/ES2015 and even includes some additional features not found in JavaScript. TypeScript code is transpiled to JavaScript, so it can be run in any JavaScript environment.
What are the benefits of using ES6/ES2015 over earlier versions of JavaScript?
Using ES6/ES2015 over earlier versions of JavaScript offers several benefits. It introduces new syntax and features that make the language more powerful and easier to use. It also improves code organization and maintainability, and it provides better support for complex applications and large codebases.
James is a full-stack software developer who has a passion for web technologies. He is currently working with a variety of languages, and has engineered solutions for the likes of Sky, Channel 4, Trainline, and NET-A-PORTER.