• The Latest Features Added to JavaScript in ECMAScript 2020
  • By Thomas Findlay
  • Translation from: The Gold Project
  • This article is permalink: github.com/xitu/gold-m…
  • Translator: Gesj – yean
  • Proofreader: Chorer, CoolRice

New features in ECMAScript 2020

JavaScriptT2 Light_1200x303

JavaScript is one of the most popular programming languages, and new features are added every year. This article describes the new features added to ECMAScript 2020, also known as ES11.

Before the introduction of ECMAScript 2015 (also known as ES6), JavaScript was evolving very slowly. But since 2015, new features have been added every year. It should be noted that not all of these features are supported by modern browsers, but thanks to the JavaScript compiler Babel, new features are available. This article introduces some of the latest features in ECMAScript 2020 (ES11).

Optional Chaining

Most developers have encountered this problem:

TypeError: Cannot read property ‘x’ of undefined

This error indicates that we are accessing a property that does not belong to the object.

Access the properties of an object

const flower = {
    colors: {
        red: true}}console.log(flower.colors.red) // It is running properly

console.log(flower.species.lily) TypeError: Cannot read property 'lily' of undefined
Copy the code

In this case, the JavaScript engine throws an error like this. But in some cases it doesn’t matter if the value exists, because we know it exists. That’s where the optional chained call comes in!

We can use an optional chain operator consisting of a question mark and a dot to indicate that an error should not be raised. If there is no value, undefined should be returned.

console.log(flower.species? .lily)/ / output is undefined
Copy the code

Optional chained calls can also be used when accessing arrays or calling functions.

Access to an array

let flowers =  ['lily'.'daisy'.'rose']

console.log(flowers[1]) // Output: Daisy

flowers = null

console.log(flowers[1]) // Raise TypeError: Cannot read property '1' of null
console.log(flowers? .1]) // Output: undefined
Copy the code

Call a function

let plantFlowers = (a)= > {
  return 'orchids'
}

console.log(plantFlowers()) // Output: orchids

plantFlowers = null

console.log(plantFlowers()) TypeError: plantFlowers is not a function

console.log(plantFlowers? . ()// Output: undefined
Copy the code

Nullish Coalescing Indicates the coalcing of an empty value

At present, to provide the fallback values for variables, logical operator | | is a must. It is suitable for many situations, but it cannot be applied in some special scenarios. For example, the initial value is a Boolean or a number. For example, if we want to assign a number to a variable, we default it to 7 when the initial value of the variable is not a number:

let number = 1
let myNumber = number || 7
Copy the code

The variable myNumber is equal to 1, because the number on the left is a true value of 1. But what happens when the variable number is 0 instead of 1?

let number = 0
let myNumber = number || 7
Copy the code

0 is false, so even if 0 is a number. The variable myNumber will be assigned the value 7 on the right. But it didn’t turn out the way we wanted. Fortunately, it consists of two question marks:?? The merge operator can check whether the variable number is a number without writing any extra code.

let number = 0
let myNumber = number ?? 7
Copy the code

The value on the right side of the operator is only valid if the value on the left is null or undefined, so the variable myNumber in the example now has a value of 0.

Private Fields Private Fields

Many programming languages with classes allow you to define classes as public, protected, or private properties. Public properties can be accessed from outside the class or from subclasses, protected properties can only be accessed by subclasses, and private properties can only be accessed from inside the class. JavaScript has supported class syntax since ES6, but it is only now that private fields have been introduced. To define a private property, you must precede it with a hash symbol: #.

class Flower { #leaf_color = "green"; constructor(name) { this.name = name; } get_color() { return this.#leaf_color; } } const orchid = new Flower("orchid"); console.log(orchid.get_color()); // Output: green console.log(orchid.#leaf_color) // Error: SyntaxError: Private field '#leaf_color' must be declared in an enclosing classCopy the code

If we access private properties of a class from the outside, we are bound to report an error.

Static Fields Static Fields

If you want to use the methods of a class, you must first instantiate a class as follows:

class Flower {
  add_leaves() {
    console.log("Adding leaves"); }}const rose = new Flower();
rose.add_leaves();

Flower.add_leaves() TypeError: flower. add_leaves is not a function
Copy the code

An attempt to access a Flower class method that has not been instantiated will throw an error. But because of static fields, class methods can be declared by static keywords and then called externally.

class Flower {
  constructor(type) {
    this.type = type;
  }
  static create_flower(type) {
    return newFlower(type); }}const rose = Flower.create_flower("rose"); // It is running properly
Copy the code

I am awaiting the patent at the Top Level

Currently, if the result of a Promise function is obtained with await, the function that uses await must be defined with the async keyword.

const func = async() = > {const response = await fetch(url)
}
Copy the code

The headache is that waiting for certain results in the global scope is almost impossible. Unless you use immediate call function expressions (IIFE).

(async() = > {const response = await fetch(url)
})()
Copy the code

But with the introduction of top-level Await, it is no longer necessary to wrap the code in an Async function, as follows:

const response = await fetch(url)
Copy the code

This feature is useful for resolving module dependencies or when an alternate source is needed because the original source is not available.

let Vue
try {
    Vue = await import('url_1_to_vue')
} catch {
    Vue = await import('url_2_to_vue)
} 
Copy the code

Promise. AllSettled method

We can use promise. all([promise_1, promise_2]) when waiting for multiple promises to return results. The problem is that if one of the requests fails, an error is thrown. However, sometimes we want the results of other requests to return normally if one request fails. For this case, ES11 introduced Promise.allSettled.

promise_1 = Promise.resolve('hello')
promise_2 = new Promise((resolve, reject) = > setTimeout(reject, 200.'problem'))

Promise.allSettled([promise_1, promise_2])
    .then(([promise_1_result, promise_2_result]) = > {
        console.log(promise_1_result) This is very depressing. // Output: {status: 'fulfilled', value: 'hello'}
        console.log(promise_2_result) // Output: {status: 'rejected', reason: 'problem'}
    })
Copy the code

A successful Promise will return an object containing status and value, and a failed promise will return an object containing status and reason.

Dynamic Import Dynamic Import

You may have used dynamic introduction in webPack’s module bindings. But native support for this feature has arrived:

// Alert.js
export default {
    show() {
        / / code}}// The file that uses alert.js
import('/components/Alert.js')
    .then(Alert= > {
        Alert.show()
    })
Copy the code

Considering that many applications use module packers such as WebPack for code translation and optimization, this feature is of little use right now.

MatchAll Matches all items

MatchAll is useful if you want to find all the matches of regular expressions and their positions in a string.

const regex = /\b(apple)+\b/;
const fruits = "pear, apple, banana, apple, orange, apple";


for (const match of fruits.match(regex)) {
  console.log(match); 
}
/ / output
// 
// 'apple' 
// 'apple'
Copy the code

MatchAll, by contrast, returns more information, including the index where the match was found.

for (const match of fruits.matchAll(regex)) {
  console.log(match);
}

/ / output
// 
/ / /
// 'apple',
// 'apple',
// index: 6,
// input: 'pear, apple, banana, apple, orange, apple',
// groups: undefined
/ /,
/ / /
// 'apple',
// 'apple',
// index: 21,
// input: 'pear, apple, banana, apple, orange, apple',
// groups: undefined
/ /,
/ / /
// 'apple',
// 'apple',
// index: 36,
// input: 'pear, apple, banana, apple, orange, apple',
// groups: undefined
// ]
Copy the code

GlobalThis Global object

JavaScript can run in different environments, such as browsers or Node.js. The global object available in the browser is the variable window, but in Node.js it is an object called global. GlobalThis was introduced in order to use the same global objects across different environments.

/ / the browser
window == globalThis // true

// node.js
global == globalThis // true
Copy the code

BigInt

The maximum number that can be expressed accurately in JavaScript is 2^ 53-1. BigInt can be used to create larger numbers.

const theBiggerNumber = 9007199254740991n
const evenBiggerNumber = BigInt(9007199254740991)
Copy the code

conclusion

I hope you found this article useful and look forward to the upcoming features of JavaScript as much as I do. To learn more, check out the TC39 Committee’s official Github repository.

If you find any errors in the translation or other areas that need improvement, you are welcome to revise and PR the translation in the Gold Translation program, and you can also get corresponding bonus points. The permanent link to this article at the beginning of this article is the MarkDown link to this article on GitHub.


Diggings translation project is a community for translating quality Internet technical articles from diggings English sharing articles. The content covers the fields of Android, iOS, front end, back end, blockchain, products, design, artificial intelligence and so on. For more high-quality translations, please keep paying attention to The Translation Project, official weibo and zhihu column.