preface

The production process of an ECMAScript standard includes five stages from Stage 0 to Stage 4. The submission of each Stage to the next Stage requires the approval of TC39. This article describes these new features as being in Stage 4, which means they should be supported in browsers and other engines soon

ES2020 is the 2020 version of ECMAScript. This release does not contain as many new features as ES6 (ES2015). But many interesting and useful features have also been added.

Technical Committee 39 (TC39) of ECMA is responsible for developing the ECMAScript standard. Its members include Microsoft, Mozilla, Google and others (representatives of major browser vendors).

Test262 is a report that provides JavaScript developers with the status of each browser’s implementation of new and old features of the ECMAScript language. It relies on running ecMA-262 test cases in various JavaScript engines on a daily basis to visualize the level of implementation of language features on the website (test262.report/) **


Optional Chaining operators

Stage 4

Optional chains allow us to query objects with multiple levels without the need for redundant pre-validation. Uncaught TypeError: Cannot read Property Uncaught TypeError: Cannot read Property Uncaught TypeError: Cannot read Property… This error causes the entire program to abort.

Therefore, you need to modify your code to handle each possible undefined object in the property chain, such as:

let nestedProp = obj && obj.first && obj.first.second;
Copy the code

Before accessing obj.first.second, make sure that the values of obj and obj.first are not null(and not undefined). With the optional chain call, similar tedious front-check operations can be greatly simplified and more secure:

letnestedProp = obj? .first? .second;Copy the code

If obj or obj.first is null/undefined, the expression will short-circuit the evaluation and return undefined directly.

Browser support:

Test262 Report:

MDN documentation: developer.mozilla.org/zh-CN/docs/…


The Nullish coalescing Operator

Stage 4

** null value merge operator (??) ** is a logical operator. When the left-hand operand is null or undefined, it returns the right-hand operand. Otherwise return the left-hand operand.

In daily development, when we query an attribute, we often set a default value without the attribute, for example, in the following two ways:

let c = a ? a : b 1 / / way
let c = a || b 2 / / way
Copy the code

One obvious drawback of both approaches is that they overwrite all false values, such as (0, “, false), which may be valid inputs in certain situations.

let x = {
  profile: {
    name: 'Guess who I am'.age: ' '}}console.log(x.profile.age || 18) / / 18
Copy the code

In the example above, the age attribute is an empty string, which is equivalent to a false value. To solve this problem, ES2020 has a new feature — the void merge operator, which uses?? Said. If the expression is in?? Returns the default value on the right of the operator evaluated to undefined or null.

et c = a ?? b;
// let c = a! == undefined && a ! == null ? a : b;
Copy the code

For example, there is the following code:

const x = null;
const y = x ?? 500;
console.log(y); / / 500
const n = 0
const m = n ?? 9000;
console.log(m) / / 0
Copy the code

Browser support:

Test262 Report:

MDN documentation: developer.mozilla.org/zh-CN/docs/…


BigInt

** Stage: Stage 4 ** ** One of the reasons javascript has always been terrible at Math is that it can only safely represent values from -(2^53-1) to the 2^53-1 normal, From number. MIN_SAFE_INTEGER to number. MAX_SAFE_INTEGER, integers outside this range are calculated or indicate loss of precision.

var num = Number.MAX_SAFE_INTEGER;  / / - > 9007199254740991
num = num + 1; / / - > 9007199254740992
// Add +1 again
num = num + 1; / / - > 9007199254740992
// Two different values, but return true
9007199254740992= = =9007199254740993  // -> true
Copy the code

Hence BigInt, the seventh primitive type that can safely evaluate large integers. You can use the same operators on BigInt as normal numbers, such as +, -, /, *, %, etc. Creating a value of type BigInt is also as simple as adding n after the number. For example, 123 changes to 123N. It can also be converted using the global BigInt(value) method, which takes a value as a number or a numeric string.

const aNumber = 111;
const aBigInt = BigInt(aNumber);
aBigInt === 111n // true
typeof aBigInt === 'bigint' // true
typeof 111 // "number"
typeof 111n // "bigint"
Copy the code

Just add n to the end of the number to calculate large numbers correctly:

1234567890123456789n * 123n;
// -> 151851850485185185047n
Copy the code

One problem, however, is that you cannot mix BigInt with Number in most operations. It is ok to compare Number and BigInt, but not to add them.

1n < 2 
// true
1n + 2
// Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions
Copy the code

Browser support:

Test262 Report:

TC39: TC39. Es/proposal – bi…

MDN documentation: developer.mozilla.org/zh-CN/docs/…


globalThis

Stage 4 (ECMAScript Latest Draft (ECMA-262))

GlobalThis is a new standard method for retrieving globalThis. Previously, developers would get it in the following ways:

  • The global variable window: is a classic method for getting global objects. However, it is not available in Node.js and Web Workers
  • The global variable self: usually only works in Web Workers and browsers. But it does not support Node.js. Some people identify code running in Web Workers and browsers by checking the presence of self
  • The global variable global: is valid only in Node.js

In the past, global objects can be obtained through a global function:

// Pre-ES10 solution
const getGlobal = function(){
  if(typeofself ! = ='undefined') return self
  if(typeof window! = ='undefined') return window
  if(typeof global! = ='undefined') return global
  throw new Error('unable to locate global object')}/ / ES10 built-in
globalThis.Array(0.1.2) / / [0]
// Define a global object v = {value:true},ES10 is defined as follows
globalThis.v = { value:true }
Copy the code

The purpose of globalThis is to provide a standardized way to access global objects. With globalThis, you can access global objects in any context at any time. GlobalThis will be Window if you are on a browser, and global if you are on Node. As a result, there is no longer a need to consider different environmental issues.

// worker.js
globalThis === self
// node.js
globalThis === global
// browser.js
globalThis === window
Copy the code

The new proposal also states that Object.prototype must be in the global Object’s prototype chain. The following code already returns true in recent browsers:

Object.prototype.isPrototypeOf(globalThis); // true
Copy the code

Browser support:

Test262 Report:

MDN documentation: developer.mozilla.org/zh-CN/docs/…


Promise.allSettled

** ** We know promise.all has the ability to execute asynchronous tasks concurrently. The biggest problem is that if either promise is reject, the entire promise. all call immediately terminates ** and returns a reject new promise object.

const promises = [
 Promise.resolve(1),
 Promise.resolve(2),
 Promise.reject('error')];Promise.all(promises)
 .then(responses= > console.log(responses))
 .catch(e= > console.log(e)) // "error"Copy the codeCopy the code

Imagine a scenario like this: A page has three areas corresponding to three independent interface data. Use promise. all to request three interfaces concurrently. If any interface is abnormal, the state is reject. Promise. AllSettled this pain point:

Promise.allSettled([
  Promise.reject({ code: 500.msg: 'Service exception' }),
  Promise.resolve({ code: 200.list: []}),Promise.resolve({ code: 200.list: [] })
]).then(res= > {
  console.log(res)
  /* 0: {status: "Rejected ", reason: {... }} 1: {status: "depressing ", value: {... This is a big pity. 1: {status: "depressing ", value: {... }} * /
  // Filter out the Rejected state to ensure as much page area data rendering as possible
  RenderContent(
    res.filter(el= > {
      returnel.status ! = ='rejected'}})))Copy the code

**Promise.allSettled is similar to promise.all, in that it accepts an array of promises and returns a new Promise, except that it will not be short-circuited. This means that when all promises are processed, we can get the state of each Promise, regardless of whether they were processed successfully or not.

Browser support:

Test262 Report:

MDN documentation: developer.mozilla.org/zh-CN/docs/…


String.prototype.matchAll

** ** If a regular expression has more than one match in a string, it is now common to use the G modifier or y modifier to retrieve each match in a loop.

function collectGroup1 (regExp, str) {
  const matches = []
  while (true) {
    const match = regExp.exec(str)
    if (match === null) break
    matches.push(match[1])}return matches
}
console.log(collectGroup1(/"([^"]*)"/g.`"foo" and "bar" and "baz"`))
// [ 'foo', 'bar', 'baz' ]Copy the codeCopy the code

It is worth noting that without the modifier /g,.exec() returns only the first match. Now through the String. The prototype. MatchAll method, can one-time remove all matching.

function collectGroup1 (regExp, str) {
  let results = []
  for (const match of str.matchAll(regExp)) {
    results.push(match[1])}return results
}
console.log(collectGroup1(/"([^"]*)"/g.`"foo" and "bar" and "baz"`))
// ["foo", "bar", "baz"]Copy the codeCopy the code

MatchAll (regex) returns a traverser, so we can use for… Of loop out.

Browser support:

Test262 Report:

MDN documentation: developer.mozilla.org/zh-CN/docs/…


Dynamic import

* * in stages: Stage 4 * * * * now front packaging resources more and more big, the front-end application initialization time don’t need to load all these logical resources, in order to first screen rendering speed faster, a lot of moment are dynamically import load (on-demand) modules, such as lazy loading pictures, etc., which can help you to improve the performance of the application. Loading these logical resources on demand is usually done in an event callback:

el.onclick = () = > {
  import('/modules/my-module.js')
    .then(module= > {
      // Do something with the module.
    })
    .catch(err= > {
      // load error;})} copy the codeCopy the code

Import () can be used in script scripts, and the import(module) function can be called from anywhere. It returns a promise resolved as a module object. This usage also supports the await keyword.

let module = await import('/modules/my-module.js'); Copy the codeCopy the code

By importing code dynamically, you can reduce the time it takes for your application to load and get something back to the user as quickly as possible.

Browser support:

Test262 Report:

MDN documentation: developer.mozilla.org/zh-CN/docs/…


Stage 0 through Stage 4

** Stage 0: Strawman Stage

Brainstorming proposals are a free form to advance ECMAScript and can be submitted by any TC39 member, or registered as a TC39 contributor.

** This Stage produces a formal Proposal.

Identify a leader for the proposal, the leader or co-leader must be a member of TC39. Describe the problem to be solved, and the solution must include examples, apis, and relevant semantics and algorithms. Potential problems should also be pointed out, such as relationships with other features, and the challenges of implementing it. Polyfills and demos are also necessary.

Stage 2: The Draft

The draft is the first version of the specification and will not differ significantly from the features contained in the final standard. After the draft, only incremental amendments are accepted in principle.

The draft contains as complete a formal description of the syntax and semantics of the new feature as possible, allowing the inclusion of to-do items or placeholders. Two experimental implementations must be included, one of which can be implemented using a translator, such as Babel.

This is Stage 3.

Candidate phase, get implementation and user feedback. Thereafter, changes will be made only if major problems arise in implementation and use.

The specification document must be complete, with reviewers and ECMAScript editors signing off on the specification. There must be at least two implementations that conform to the specification.

Stage 4: Finished

This feature is ready to appear in the annual release of the specification.

Pass the acceptance Test of TEST-262. There are two implementations that have been tested to gain important practical experience in their use. ECMAScript edits must be signed on the specification.


Reference: MDN documentation TC39 Proposals github.com/tc39/test26… Dev. To/carlillo/es…