What’s new in ECMA / JavaScript cheat sheet
ECMAScript 2022 - 4 Finished proposals
1. RegExp Match Indices
Proposal • MDN • v8.dev
Using the regex d
flag, additionally return the start and end indices for individual capture groups on regex matches.
/(?<x>a)(?<y>b)/d.exec('ab')
// ['ab', 'a', 'b']
/(?<x>a)(?<y>b)/d.exec('ab').indices
// [[0, 2], [0, 1], [1, 2]]
/(?<x>a)(?<y>b)/d.exec('ab').indices.groups
// { x: [0, 1], y: [1, 2] }
✅ Chrome - Since v90
✅ Firefox - Since v89
🟡 Safari - Since v15? (not mentioned in release notes) technical preview 122
✅ Node - Since v16.0.0 (v8 9.0)
CanIUse - unavailable
2. Top-level await
Proposal • MDN • v8.dev
use await
outside async functions in a module.
await Promise.resolve(console.log('🎉'));
✅ Babel
✅ Typescript - Since v3.8
✅ SWC
✅ Sucrase
✅ Chrome - Since v89
✅ Firefox - Since v89
🟡 Safari - Since v15 technical preview 122
✅ Node - Since v16.4.0 - not in commonjs modules (v8 9.1)
CanIUse
3. Class Fields
a. Class Instance Fields
Proposal
Declare fields (this.variable
) outside constructor. Create private fields which cannot be accessed from outside the class.
class Fields {
x = 0;
#y = 0;
constructor() {
this.x = 0;
this.#y = 1;
}
}
const obj = new Fields();
console.log(obj.x); // 0
console.log(obj.#y); // error
b. Private instance methods and accessors
Proposal
Add private methods and accessors (getter/setters).
class Example {
#xValue = 0;
get #x() {
return #xValue;
}
set #x(value) {
this.#xValue = value;
}
#add() {
this.#x = this.#x + 2;
}
constructor() {
this.#add();
}
}
c. Static class fields and private static methods
class StaticMethodCall {
static #privateStaticProperty = 'private static property';
static staticProperty = 'static property';
static staticMethod() {
}
static #privateStaticMethod() {
}
}
StaticMethodCall.staticMethod();
4. Ergonomic brand checks for Private Fields
Proposal • MDN • v8.dev
Check if a private field exists in an object using the in
operator.
class C {
#brand;
#method() {}
get #getter() {}
static isC(obj) {
return #brand in obj && #method in obj && #getter in obj;
}
}
✅ Babel
⛔ Typescript
⛔ SWC
⛔ Sucrase
✅ Chrome - Since v91
✅ Firefox - Since v90
🟡 Safari - Since v15? (not mentioned in release notes) technical preview 127
✅ Node - Since v16.4.0 (v8 9.1)
CanIUse - Not available
ECMAScript 2021 - 5 new features
1. Numeric separators [new syntax]
MDN • v8.dev
Allow making numbers more readable by separating it with _
(underscore)
let budget = 1_000_000_000_000;
✅ Babel
✅ Typescript - Since v2.7
✅ SWC
✅ Sucrase
✅ Chrome - Since v75
✅ Firefox - Since v70
✅ Safari - Since v13
✅ Node - Since v12.5.0
CanIUse
2. Logical Assignment Operators [new syntax]
MDN • v8.dev
Combine Logical Operators and Assignment Expressions
// "Or Or Equals"
a ||= b;
a || (a = b);
// "And And Equals"
a &&= b;
a && (a = b);
// "QQ Equals"
a ??= b;
a ?? (a = b);
✅ Babel
✅ Typescript - Since v4.0
⛔ SWC
⛔ Sucrase
✅ Chrome - Since v85
✅ Firefox - Since v79
✅ Safari - Since v14
✅ Node - Since v15.0.0
CanIUse
3. WeakRefs [new object]
MDN • v8.dev
A WeakRef object lets you hold a weak reference to another object, without preventing that object from getting garbage-collected.
Related: FinalizationRegistry
const ref = new WeakRef(someObject);
// Try to reference the original object
const obj = ref.deref();
if (obj) {
console.log('The obj is available.');
} else {
console.log('The obj has been removed.');
}
✅ Chrome - Since v84
✅ Firefox - Since v79
✅ Safari - Since v14 (iOS Safari v14.7)
✅ Node - Since v14.6.0
CanIUse
Cannot be polyfilled
4. Promise.any [new method]
MDN • v8.dev
Takes a list of Promises (or iterable) and as soon as one of the promises fulfills(resolves), returns a single promise that resolves with the value from that promise. If no promise fulfills (if all of the given promises are rejected), then the returned promise is rejected with an AggregateError.
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));
// output: "quick"
✅ Chrome - Since v89
✅ Firefox - Since v86
✅ Safari - Since v14
✅ Node - Since v15.0.0
CanIUse
Polyfill
5. String.prototype.replaceAll [new method]
MDN • v8.dev
Replace all instances of a substring (literal or regexp) in a string
const queryString = 'q=query+string+parameters';
const withSpaces = queryString.replaceAll('+', ' ');
✅ Chrome - Since v85
✅ Firefox - Since v77
✅ Safari - Since v13.1
✅ Node - Since v15.0.0
CanIUse
Polyfill
ECMAScript 2020 - 9 new features
1. import.meta [new object]
MDN • v8.dev
The import.meta
is a special object which contains metadata of the currently running JavaScript module.
import
is not an object, only import.meta
is an object. This object is mutable and can be used to store arbitrary information.
Example usage in deno.
Example usage in vite.
// Load a module
<script type="module" src="my-module.js"></script>
// my-module.js
console.log(import.meta); // { url: "<url>" }
✅ Chrome - Since v64
✅ Firefox - Since v62
✅ Safari - Since v11.1 (iOS Safari v12)
✅ Node - Since v10.4.0
CanIUse
2. Nullish coalescing Operator [new syntax]
MDN • v8.dev
The nullish coalescing operator ??
is a logical operator that returns its right-hand side operand when its left-hand side operand is null or undefined, and otherwise returns its left-hand side operand.
let x = foo ?? bar();
// Which is equivalent to
let x = (foo !== null && foo !== undefined) ? foo : bar();
✅ Babel
✅ Typescript - Since v3.7
✅ SWC
✅ Sucrase
✅ Chrome - Since v80
✅ Firefox - Since v72
✅ Safari - Since v13.1 (iOS Safari v13.7)
✅ Node - Since v14.0.0
CanIUse
3. Optional Chaining [new syntax]
MDN • v8.dev
The ?.
operator functions similarly to the .
chaining operator, except that instead of causing an error if a reference is nullish (null or undefined), the expression short-circuits with a return value of undefined.
let x = foo?.bar.baz();
// Which is equivalent to
let x = (foo === null || foo === undefined) ? undefined : foo.bar.baz();
// Calling an optional method
myForm.checkValidity?.()
✅ Babel
✅ Typescript - Since v3.7
✅ SWC
✅ Sucrase
✅ Chrome - Since v80
✅ Firefox - Since v72
✅ Safari - Since v13.1 (iOS Safari v13.7)
✅ Node - Since v14.0.0
CanIUse
4. for-in mechanics [new behavior]
Proposal
Standardize the order of for-in loops.
5. globalThis [new object]
MDN • v8.dev
Standard way to access the global object in all JavaScript environments (window in Browser, global in Node).
function canMakeHTTPRequest() {
return typeof globalThis.XMLHttpRequest === 'function';
}
✅ Typescript lib - Since v3.4
✅ Chrome - Since v71
✅ Firefox - Since v65
✅ Safari - Since v12.1 (iOS Safari v12.2)
✅ Node - Since v12.0.0
Polyfill
CanIUse
6. Promise.allSettled [new method]
MDN • v8.dev
Promise.allSettled
is a new Promise method that returns a Promise that is fulfilled when all of the input promises are fulfilled or rejected.
const promises = [ fetch('index.html'), fetch('https://does-not-exist/') ];
const results = await Promise.allSettled(promises);
const successfulPromises = results.filter(p => p.status === 'fulfilled');
✅ Typescript lib - Since v3.8
✅ Chrome - Since v76
✅ Firefox - Since v71
✅ Safari - Since v13
✅ Node - Since v12.0.0
Polyfill
CanIUse
7. BigInt [new object]
MDN • v8.dev
The BigInt
type is a new numeric primitive in ECMAScript, which is a signed integer type.
BigInt would dynamically resize memory to fit the actual value.
The maximum size of BigInt is unspecified and left to the implementation.
https://stackoverflow.com/a/54298760
https://github.com/tc39/proposal-bigint/issues/174
https://v8.dev/blog/bigint
const huge = BigInt(9007199254740991)
// 9007199254740991n
// BigInt numbers end with a "n".
✅ Typescript lib - Since v3.8
✅ Chrome - Since v67
✅ Firefox - Since v68
✅ Safari - Since v14 (iOS Safari v14.4)
✅ Node - Since v10.4.0
CanIUse
Cannot be polyfilled
8. Dynamic import - import()
[new method]
MDN • v8.dev
Dynamic imports allows you to import modules at run-time.
import('/modules/my-module.js')
.then(module => {
module.loadPageInto(main);
})
.catch(err => {
main.textContent = err.message;
});
✅ Babel
✅ Typescript - Since v2.4
✅ SWC
✅ Sucrase
✅ Chrome - Since v63
✅ Firefox - Since v67
✅ Safari - Since v11.1 (iOS Safari v11.3)
✅ Node - Since v13.2.0, later enabled in v12.17.0
CanIUse
9. String.prototype.matchAll [new method]
MDN • v8.dev
matchAll
returns a RegExpStringIterator of matches matching a string or regex also with capture groups.
const regexp = /t(e)(st(\d?))/g;
const str = 'test1test2';
const match = str.matchAll(regexp);
for (const m of str.matchAll(regexp)) {
console.log(m);
}
// ["test1", "e", "st1", "1"]
// ["test2", "e", "st2", "2"]
✅ Typescript lib - Since v3.8
✅ Chrome - Since v63
✅ Firefox - Since v67
✅ Safari - Since v11.1 (iOS Safari v11.3)
✅ Node - Since v13.2.0, later enabled in v12.17.0
CanIUse
ECMAScript 2019 - 8 new features
1. Array.prototype.{flat,flatMap}
Proposal • MDN-flat • MDN-flatMap • v8.dev
flat
- Create a new array with sub-array elements concatenated into it recursively up to the specified depth.
flatMap
- Map over and flatten an array (to 1 level). Equivalent to running Array.prototype.map
then Array.prototype.flat
with depth 1.
const arr2 = [0, 1, 2, [[[3, 4]]]];
console.log(arr2.flat(3));
// [0, 1, 2, 3, 4]
let arr = [[1, 3], [4, 6], [7, 9], [10, 12]];
console.log(arr.flatMap(x => [x[0], (x[0] + x[1]) / 2, x[1]]));
// [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ]
2. String.prototype.{trimStart,trimEnd}
Proposal • MDN-trimStart • MDN-trimEnd • v8.dev
const string = ' hello world ';
string.trimStart();
// 'hello world '
string.trimEnd();
// ' hello world'
CanIUse - trimStart
CanIUse - trimEnd
3. Well-formed JSON.stringify
Proposal • MDN • v8.dev
Stringify lone surrogates i.e. any code point from U+D800 to U+DFFF, using Unicode escape sequences. Before this change JSON.stringify would output lone surrogates if the input contained any lone surrogates; such strings could not be encoded in valid UTF-8 or UTF-16:
// Before
JSON.stringify("\uD800"); // '"�"'
// After
JSON.stringify("\uD800"); // '"\\ud800"'
4. Object.fromEntries
Proposal • MDN • v8.dev
It accepts an iterable of key-value pairs and returns a new object whose own keys and corresponding values are given by those pairs.
obj = Object.fromEntries([['a', 0], ['b', 1]]);
// { a: 0, b: 1 }
5. Function.prototype.toString revision
6. Symbol.prototype.description
const symbol = Symbol('foo');
symbol.description;
// 'foo'
7. JSON superset
Proposal • MDN • v8.dev
JSON becomes a syntactic subset of ECMAScript. Before this, ECMAScript string literals couldn’t contain unescaped U+2028 LINE SEPARATOR and U+2029 PARAGRAPH SEPARATOR characters which JSON could have.
8. Optional catch binding
try {
doSomethingThatMightThrow();
} catch { // catch parameter is now optional
handleException();
}