ES9

preface

This article focuses on some of the new features added to ES9.

1. Asynchronous iteration

At some point in async/await, you may try to call an asynchronous function in a synchronous loop. Such as:

async function process(array) {
  for (let i of array) {
    await doSomething(i); }} Copy the codeCopy the code

This code won’t work, and neither will the following:

async function process(array) {
  array.forEach(async i => {
    await doSomething(i); }); } copy codeCopy the code

In this code, the loop itself remains synchronized and is fully called before the internal asynchronous function.

ES2018 introduces asynchronous iterators, which are just like regular iterators except that the next() method returns a Promise. So await can be combined with for… Of loop to run asynchronous operations in a serial manner. Such as:

async function process(array) {
  for await (let i of array) {
    doSomething(i); }}Copy the code

2. Promise.finally()

In ES6, a Promise chain either successfully enters the last then() or fails to trigger a catch(). In practice, we might want to run the same code whether the Promise succeeds or fails. For example, clear, delete reply, close the database connection and other operations.

In ES9, finally() is allowed to specify the final logic.

As follows:

        let count = () => {
            return new Promise((resolve, reject) => {
                setTimeout(() => { resolve(100) }, 1000); })}let list = () => {
            return new Promise((resolve, reject) => {
                setTimeout(() => { resolve([1, 2, 3]) }, 1000); })}let getList = async () => {
            let c = await count()
            console.log('async')
            let l = await list()
            return { count: c, list: l }
        }
        console.time('start');
        getList().then(res => {
            console.log(res)
        })
        .catch(err => {
            console.timeEnd('start')
            console.log(err)
        })
        .finally(() => {
            console.log('finally')}) async {count: 100, list: [1, 2, 3]} finallyCopy the code

3. The Rest/Spread properties

3.1 the ES6 (…).

There are three things introduced in ES6… , which is used mainly for Rest parameters and extension operators:

Action objects are used only for arrays

1. Represent an array with an unknown number of arguments:

restParam(1, 2, 3, 4, 5);

functionrestParam(p1, p2, ... p3) { // p1 = 1 // p2 = 2 // p3 = [3, 4, 5] }Copy the code

2. Extension operators:

const values = [99, 100, -1, 48, 16]; console.log( Math.max(... values) ); / / 100Copy the code

3.2 the ES9 (…).

In ES9, objects are provided with Rest parameters and expansion operators that act like arrays.

Rest Parameter Usage

var obj = { a: 1, b: 2, c: 3 } const { a, ... param } = obj; console.log(a) //1 console.log(param) //{b: 2, c: 3}Copy the code

Spread, used to collect all remaining parameters:

        var obj = {
            a: 1,
            b: 2,
            c: 3
        }
		functionfoo({a, ... param}) { console.log(a); console.log(param) }Copy the code

As with arrays, Rest parameters can only be used at the end of the declaration. In addition, it only applies at the top level of each object, not if there are nested objects in the object.

Extension operators can be used within other objects

const obj1 = { a: 1, b: 2, c: 3 }; const obj2 = { ... obj1, z: 26 }; // obj2 is { a: 1, b: 2, c: 3, z: 26 }Copy the code

3.3 Usage scenarios of Spread

1. The shallow copy

Take advantage of To copy an object, but this copy can only copy the enumerable properties of the object.

        var obj = {
            name: 'LinDaiDai',
            looks: 'handsome'.foo() {
                console.log('old');
            },
            set setLooks(newVal) {
                this.looks = newVal
            },
            get getName() {
                console.log(this.name)
            }
        }

        var cloneObj = {... obj};cloneObj.foo = function() {
            console.log('new')}; console.log(obj) // { name:'LinDaiDai',looks: 'handsome', foo: f foo(), get getName:f getName(), set setLooks: f setLooks(newVal)}
        console.log(cloneObj)
        // { name: 'LinDaiDai',looks: 'handsome', foo: f foo(), getName: undefined, setLooks: undefined }
        obj.foo()
        // old
        cloneObj.foo()
        // new 
Copy the code

As shown above, an object obj is defined and used with (…) Changing foo() does not affect the original object, but the setter and getter of the original object cannot be copied.

2. Merge two objects

const merged = {... obj1, ... obj2}; Const merged = object.assign ({}, obj1, obj2);Copy the code

4. The regular expression is used to name the capture group

4.1 Basic Usage

Matching with exec() in a Javascript regular expression returns an object, an array of classes containing the matched string.

Match date format in the following example:

/ / group named regular expression to capture the const reDate = / (\ d {4}) - (\ d {2}) - (\ d {2}) /, match = reDate. Exec ('2018-08-06'); console.log(match); [2018-08-06, 2018, 08, 06] match[1] // 2018 match[2] // 08 match[3] // 06Copy the code

Returns an array where the 0th item is the text that matches the regular expression, the first element is the text that matches the first subexpression of RegExpObject (if any), and the second element is the text that matches the second subexpression of RegExpObject (if any). And so on.

In the above example, changing the structure of the regular expression might change the index of the matched object.

For example, modify as follows:

/ / group named regular expression to capture the const reDate = / (\ d {2}) - (\ d {2}) - (\ d {4}) /, match = reDate. Exec ('2018-08-06'); console.log(match); [2018-08-06, 08, 06, 2018] match[3] // 2018 match[1] // 08 match[2] //Copy the code

You can see the drawbacks of writing above, so in ES9 you can use symbols for named capture groups? <name>That is as follows:

const reDate = /(? <year>\d{4})-(? <month>\d{2})-(? <day>\d{2})/, match = reDate.exec('2018-08-06') console.log(match); // [2018-08-06, 08, 06, 2018, groups: {day: 06, month: 08, year: Year // 2018 match-.groups. Month // 08 match-.groups. Day // 06Copy the code

Naming a capture group is written in the same way as defining a name for each matched capture group and storing it in the groups property of the return value.

4.2 combined withreplace()

Named capture can also be used in the replace() method. For example, to convert a date to the U.S. format MM-DD-YYYY:

const reDate = /(? <year>\d{4})-(? <month>\d{2})-(? <day>\d{2})/, d ='2018-08-06'
      USADate = d.replace(reDate, '$<month>-$<day>-$<year>'); console.log(USADate); / / 08-06-2018Copy the code

We can also exchange the first and last names of Chinese names:

const reName = /(? <sur>[a-zA-Z]+)-(? <name>[a-zA-Z]+)/; Chinese ='Lin-DaiDai',
      USA = Chinese.replace(reName, '$<name>-$<sur>');
console.log(USA);
// DaiDai-Lin
Copy the code

5. Regular expression reverse assertion

5.1 Basic Usage

Let’s first look at what regular expression preemptive assertions are:

For example, get the symbol of the currency

const noReLookahead = /\D(\d+)/, reLookahead = /\D(? =\d+)/, match1 = noReLookahead.exec('$123.45'),
              match2 = reLookahead.exec('$123.45');
        console.log(match1[0]); // The $123console.log(match2[0]); / / $Copy the code

You can see that if I put in a regular expression? =, a match occurs, but there is no catch, and the assertion is not included in the entire match field.

In ES9, reverse assertions are allowed:

const reLookahead = /(? <=\D)[\d\.]+/; match = reLookahead.exec('$123.45'); console.log(match[0]); / / 123.45Copy the code

Use? <= makes a reverse assertion, which can be used to get the price of the currency, ignoring the currency sign.

5.2 Affirm reverse assertions

The case above is affirmative reverse assertion, which means that the condition \D must exist if:

const reLookahead = /(? <=\D)[\d\.]+/; match1 = reLookahead.exec('123.45'),
              match2 = reLookahead.exec('12345');
        console.log(match1[0]); // 45
        console.log(match2);  // null
Copy the code

You can see that match1 matches 45, and since there is nothing in front of 123 that matches \D, it will always find anything that matches \D, which is equal to. And then you go back to what’s next.

Null is returned if the previous conditions for affirming the reverse assertion are not met.

6. Regular expressionsdotAllmodel

Midpoint of a regular expression. Matches any single character except carriage return, and the s flag changes this behavior to allow line terminators:

/hello.world/.test('hello\nworld');  // false

/hello.world/s.test('hello\nworld'); // true

console.log(/hello.world/s.test(`hello
world`))   // true
Copy the code

7. Regular expression Unicode escapes

Until now, local access to Unicode character properties in regular expressions has not been allowed. ES2018 added Unicode attribute escapes — form \p{… } and \ {P… }, using the u (Unicode) tag in the regular expression, and within the \p block, you can set the attribute to match as a key-value pair rather than the actual content.

    const reGreekSymbol = /\p{Script=Greek}/u;
    console.log(reGreekSymbol.test('PI.)); // true
Copy the code

A: What’s the meaning of Greek to You?

8. Template strings that are not escape sequences

Finally, ES2018 removes the syntactic restrictions on ECMAScript escaping sequences in labeled template strings.

Before, \u starts a Unicode escape, \x starts a hexadecimal escape, \ followed by a number starts an octal escape. This makes it impossible to create specific strings, such as Windows file path C:\uuu\ XXX \111. Refer to the template string for more details.

After the language

Intellectual property is priceless and supports originality.

Reference article:

New features of ES2018 (ES9)

ES2018 New Features: Rest/Spread features

ES6/ES7/ES8/ES9 can see that javascript does not disappoint us, the update in the past few years did not fall behind, continuous learning, to ensure their own society eliminated…