The Latest Features Added to JavaScript in ECMAScript 2020

栏目: IT技术 · 发布时间: 6年前

内容简介:JavaScript is one of the most popular programming languages, and features are now added to the language every year. This article covers new features added in ECMAScript 2020, also known as ES11.Before the introduction of ECMAScript 2015, also known as ES6,

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

Before the introduction of ECMAScript 2015, also known as ES6, JavaScript language development had a very slow pace. Fortunately, since then, new features are added every year. Be aware that not all features might be supported in all modern browsers yet, but thanks to transpilers like Babel , we can use them already today. This article will cover some of the latest additions to JavaScript — ECMAScript 2020 (ES11).

Optional Chaining

I’m sure that most developers are familiar with an error of this kind:

TypeError: Cannot read property ‘x’ of undefined

This error basically means that we tried to access a property on something that is not an object.

Accessing an Object Property

const flower = {
    colors: {
        red: true
    }
}

console.log(flower.colors.red) // this will work

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

JavaScript engine will always throw an error in a scenario like this. However, there are cases in which it doesn't matter that the value isn't there yet, because we might know it will be. Fortunately, here is the optional chaining feature to the rescue!

We can use the optional chaining operator, which consists of a question mark and a dot: ?. , to indicate that an error should not be thrown. Instead, if there is no value, undefined will be returned.

console.log(flower.species?.lily) // undefined

Optional chaining can also be used when accessing array values or calling a function.

Accessing an Array

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

console.log(flowers[1]) // daisy

flowers = null

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

Calling a Function

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

console.log(plantFlowers()) // orchids

plantFlowers = null

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

console.log(plantFlowers?.()) // undefined

Nullish Coalescing

Until recently, whenever there was a need to provide a fallback value, the logical operator || had to be used. It works in most cases, but it can't be applied in some scenarios. For instance, if the initial value is a Boolean or a number. Let's take a look at an example below, where we want to assign a number to a variable, or default it to 7 if the initial value is not a number:

let number = 1
let myNumber = number || 7

The myNumber variable is equal to 1, because the left-hand value ( number ) is a truthy value, as 1 is a positive number. However, what if the number variable is not 1, but 0?

let number = 0
let myNumber = number || 7

0 is a falsy value, and even though it is a number, the myNumber variable will have the right-hand value assigned to it. Therefore, myNumber is now equal to 7. However, that's not really what we want. Fortunately, instead of writing additional code and checks to confirm if the number variable is indeed a number, we can use the nullish coalescing operator. It consists of two question marks: ?? .

let number = 0
let myNumber = number ?? 7

The right-hand side value will only be assigned if the left-hand value is equal to null or undefined . Therefore, in the example above, the myNumber variable is equal to 0.

Private Fields

Many programming languages that have classes allow defining class properties as public, protected, or private. Public properties can be accessed from outside of a class and by its subclasses, while protected classes can only be accessed by subclasses. However, private properties can only be accessed from inside of a class. JavaScript supports class syntax since ES6 , but only now were private fields introduced. To define a private property, it has to be prefixed with the 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()); // green
console.log(orchid.#leaf_color) // Private name #leaf_color is not defined

If we try to access a private property from outside, an error will be thrown.

Static Fields

To use a class method, a class had to be instantiated first, as shown below.

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

Trying to access a method without instantiating the Flower class would result in an error. Thanks to static fields, a class method can now be declared with the static keyword and called from outside of a class.

class Flower {
  constructor(type) {
    this.type = type;
  }
  static create_flower(type) {
    return new Flower(type);
  }
}

const rose = Flower.create_flower("rose"); // Works fine

Top Level Await

So far, to await for a promise to finish, a function in which await is used would need to be defined with the async keyword.

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

Unfortunately, if there was a need to await for something in a global scope, it would not be possible, and usually required an immediately invoked function expression (IIFE) .

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

Thanks to Top Level Await , there is no need for wrapping code in an async function anymore, and this code will work.

const response = await fetch(url)

This feature could be useful for resolving module dependencies or using a fallback source if the initial one failed.

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

Promise.allSettled

To wait for multiple promises to finish, Promise.all([promise_1, promise_2]) can be used. The problem is that if one of them fails, then an error will be thrown. Nevertheless, there are cases in which it is ok for one of the promises to fail, and the rest should still resolve. To achieve that, ES11 introduced Promise.allSettled .

promise_1 = Promise.resolve('hello')
primise_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) // {status: 'fulfilled', value: 'hello'}
        console.log(promise_2_result) // {status: 'rejected', reason: 'problem'}
    })

A resolved promise will return an object with status and value properties, while rejected ones will have status and reason .

Dynamic Import

You might have used dynamic imports when using webpack for module bundling. Finally, native support for this feature is here.

// Alert.js file
export default {
    show() {
        // Your alert
    }
}


// Some other file
import('/components/Alert.js')
    .then(Alert => {
        Alert.show()
    })

Considering the fact that a lot applications use module bundlers like webpack for transpiling and optimizing code, this feature isn't such a big deal right now.

MatchAll

MatchAll is useful for applying the same regular expression to a string if you need to find all matches and get their positions. The match method only returns items that were matched.

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'

matchAll in contrast, returns a bit more information, including index of the string 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
// ]

globalThis

JavaScript can run in different environments like browsers or Node.js. A global object in browsers is available under window variable, but in Node it is an object called global . To make it easier to use a global object no matter in which environment code is running, globalThis was introduced.

// In a browser
window == globalThis // true

// In node.js
global == globalThis // true

BigInt

The maximum number that can be reliably represented in JavaScript is 2^53 - 1. BigInt will allow creation of numbers even bigger than that.

const theBiggerNumber = 9007199254740991n
const evenBiggerNumber = BigInt(9007199254740991)

Conclusion

I hope you found this article useful and are as excited as I am about the new features that are coming to JavaScript. If you would like to know more about different features you can check the official GitHub repository of the ES committee here .


以上所述就是小编给大家介绍的《The Latest Features Added to JavaScript in ECMAScript 2020》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

决战大数据

决战大数据

车品觉 / 浙江人民出版社 / 2014-3-1 / 45.9

[内容简介]  大数据时代的来临,给当今的商业带来了极大的冲击,多数电商人无不“谈大数据色变”,并呈现出一种观望、迷茫、手足无措的状态。车品觉,作为一名经验丰富的电商人,在敬畏大数据的同时,洞悉到了数据时代商业发展的更多契机,他创新了数据框架的建立和使用,重新量化了数据价值的指标,并挖掘了在无线数据和多屏时代下商业发展的本质……在他看来,改变思维方式,即可改变数据和商业的未来。  ......一起来看看 《决战大数据》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

在线进制转换器
在线进制转换器

各进制数互转换器

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器