Link Search Menu Expand Document

What’s new in ECMA / JavaScript cheat sheet

ECMAScript 2022 - 4 Finished proposals

1. RegExp Match Indices

ProposalMDNv8.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

ProposalMDNv8.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

v8.devMDN-1MDN-2

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

Proposal

class StaticMethodCall {
  static #privateStaticProperty = 'private static property';
  static staticProperty = 'static property';

  static staticMethod() {
  }
  static #privateStaticMethod() {
  }
}
StaticMethodCall.staticMethod();

4. Ergonomic brand checks for Private Fields

ProposalMDNv8.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]

MDNv8.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]

MDNv8.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]

MDNv8.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]

MDNv8.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]

MDNv8.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]

MDNv8.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]

MDNv8.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]

MDNv8.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]

MDNv8.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]

MDNv8.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]

MDNv8.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]

MDNv8.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]

MDNv8.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}

ProposalMDN-flatMDN-flatMapv8.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 ]

CanIUse

2. String.prototype.{trimStart,trimEnd}

ProposalMDN-trimStartMDN-trimEndv8.dev

const string = '  hello world  ';
string.trimStart();
// 'hello world  '

string.trimEnd();
// '  hello world'

CanIUse - trimStart
CanIUse - trimEnd

3. Well-formed JSON.stringify

ProposalMDNv8.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

ProposalMDNv8.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 }

CanIUse

5. Function.prototype.toString revision

ProposalExploringJS

6. Symbol.prototype.description

ProposalMDNv8.dev

const symbol = Symbol('foo');
symbol.description;
// 'foo'

CanIUse

7. JSON superset

ProposalMDNv8.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.

CanIUse

8. Optional catch binding

ProposalMDNv8.dev

try {
  doSomethingThatMightThrow();
} catch { // catch parameter is now optional
  handleException();
}

CanIUse

ECMAScript 2018 - 8 new features

1. Asynchronous Iteration

ProposalMDNv8.dev

2. Promise.prototype.finally

3. RegExp Unicode Property Escapes

4. RegExp Lookbehind Assertions

5. Rest/Spread Properties

6. RegExp named capture groups

7. s (dotAll) flag for regular expressions

8. Lifting template literal restriction

ProposalMDNv8.dev

ECMAScript 2017 - 6 new features

1. Shared memory and atomics

2. Async functions

3. Trailing commas in function parameter lists and calls

4. Object.getOwnPropertyDescriptors

5. String padding

6. Object.values/Object.entries

ECMAScript 2016 - 2 new features

1. Exponentiation operator

2. Array.prototype.includes