JavaScript ES6 and beyond
It has been 9 years since JavaScript ES6 was introduced.
In ES6 release weβve got important features as: lexical scoping ie. let
and const
, classes, arrow functions, template literals, destructuring, maps, sets and default parameters.
I clearly rembember how this release changed writing of JavaScript.
But what about subsequent releases? What have we got since then?
2016 ES7 has brought:
- Exponentiation operator
const square = 4**4
Array.prototype.includes()
[1,2,3].includes(3) // true
2017 ES8 has brought:
async
await
supportObject.entries
Object.entries({ a: 1, b: 2 }) // [['a', 1], ['b', 2]]
Object.values
Object.values({ a: 1, b: 'hello' }) // [1, 'hello']
Object.getOwnPropertyDescriptors
- String padding functions:
padStart
,padEnd
2018 ES9 has brought:
2019 ES10 has brought:
Array.prototype.flat()
[1,2,[3,4]].flat() // [1,2,3,4]
Array.prototype.flatMap()
[1,2].flatMap((x) => [x,x*2]) // [1,2,2,4]
Object.fromEntries()
Object.fromEntries([['a', 1], ['b', 2]]) // {a:1,b:2}
- String.prototype new functions
trimStart()
trimEnd()
trimLeft()
trimRight()
2020 ES11 has brought:
- BigInt supportπβ
Promise.allSettled()
π4- Nullish coalescing operator
??
- Optional chaining
?.
- globalThisπβ
export * as ns from 'module'
syntax for modulesimport.meta
πβ
2021 ES12 has brought:
String.prototype.replaceAll()
'aaabbb'.replaceAll('a','c') // cccbbb
Promise.any()
π5- Logical assignment operators
??=
,&&=
,||=
WeakRef
referencing object but allowing it to be garbage collected_
separator allowed in number literals1_000_000 // 1000000
2022 ES13 has brought:
- top-level
await
- public, private, static class fields, static initialization blocksπ6
#x in obj
syntax, to test for presence of private fields on objects\d
new RegExp flagπβTypedArray
πβcause
property onError
objects useful when re-throwing error to access original error.πβat()
for Strings, Arrays and TypedArrays'abcd'.at(-1) // d
,'abcd'.at(2) // c
Object.hasOwn()
πβ a betterObject.prototype.hasOwnProperty()
2023 ES14 has brought:
- New methods on
Array.prototype
toSorted()
returns new copy of sorted arraytoReversed()
returns new copy of reversed arraywith()
πβfindLast()
findLastIndex()
toSpliced()
#!
shebang support
2024 ES15 has brought:
\v
new RegExp flagπβPromise.withResolvers()
convinient promise constructionπβObject.groupBy
,Map.groupBy
now easier to group items based on property/valueπβAtomics.waitAsync()
useful when working with shared memory buffersπβString.prototype.isWellFormed()
andString.prototype.toWellFormed()
checks for well-formed Unicode
What is your favourite feature from above list?
If you enjoyed this article you can join my newsletter to get dose of weekly craftsmanship.
Get dose of Craftsmanship here
References
π1 Async iterator support (source)
const asyncIterator = (async function* () {
yield 1;
yield 2;
yield 3;
})();
(async () => {
for await (const value of asyncIterator) {
console.log(value);
}
})();
// Logs: 1, 2, 3
π2 Async generator support (source)
async function* createAsyncGenerator() {
yield await Promise.resolve(1);
yield await Promise.resolve(2);
yield await Promise.resolve(3);
}
const asyncGen = createAsyncGenerator();
asyncGen.next().then((res) => console.log(res.value)); // 1
asyncGen.next().then((res) => console.log(res.value)); // 2
asyncGen.next().then((res) => console.log(res.value)); // 3
π3 Promise finally()
(source)
Schedules a function to be called when the promise is settled (either fulfilled or rejected).
fetch('https://api.example.com/json-data')
.then(response => response.json())
.then(json => console.log(json))
.catch(error => console.log(error))
.finally(() => console.log('finally() called!'));
π4 Promise.allSettled()
(source)
This returned promise fulfills when all of the inputβs promises settle (including when an empty iterable is passed), with an array of objects that describe the outcome of each promise.
const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) =>
setTimeout(reject, 100, 'foo'),
);
const promises = [promise1, promise2];
Promise.allSettled(promises).then((results) =>
results.forEach((result) => console.log(result.status)),
);
// Expected output:
// "fulfilled"
// "rejected"
π5 Promise.any()
(source)
const promise1 = Promise.reject(0);
const promise2 = new Promise((resolve) => setTimeout(resolve, 100, 'quick'));
const promise3 = new Promise((resolve) => setTimeout(resolve, 500, 'slow'));
const promises = [promise1, promise2, promise3];
Promise.any(promises).then((value) => console.log(value));
// Expected output: "quick"
π6 public, private, static class fields, static initialization blocks
class ExampleClass {
instanceField;
instanceFieldWithInitializer = "instance field";
static staticField;
static staticFieldWithInitializer = "static field";
#privateField;
#privateFieldWithInitializer = 42;
static {
this.staticField = 'Static initialization block'
// Why? We can use here try...catch block.
// More than one of these blocks can be declared.
}
publicMethod() {}
static staticMethod() {}
#privateMethod() {}
static #staticPrivateMethod() {} // ExampleClass.#staticPrivateMethod()
// allowed to be called only within class
}
// The name of a static property (field or method) cannot be prototype.
// The name of a class field (static or instance) cannot be constructor.