Four useful functions in es2018

Time:2021-5-6

The es2018 specification introduces four new features. These functions include asynchronous iteration, rest / spread property, and so on,Promise.prototype.finally()And regular expression improvement. This question will help you understand how these es2018 functions work and how to use them.

Asynchronous iteration

Asynchronous iteration is one of the less discussed functions. Although there are many discussions about other functions of es2018, there is little about asynchronous iteration. Through asynchronous iteration, we can get asynchronous iterative objects and iterators.

It means that you canawaitKeywords andfor…ofLoops are used together. You can use these loops to iterate over an iteratable object. Iteratable objects include array, map, set, NodeList, arguments parameter of function, typedarray, etc.

Before es2018,for...ofThe loop is synchronous. If you try to iterate on an iteratable object that involves asynchronous operations andawait, it will not work normally. The loop itself remains synchronized and is largely ignoredawaitAnd complete the iteration before the asynchronous operation inside can be completed.

//The following code doesn't work until es2018, because the loop stays synchronized.
//Create an asynchronous function:
async function processResponses(someIterable) {
  //Iterating on an iterative object
  for (let item of someIterable) {
    //Processing items through asynchronous operations, such as promise:
    await processItem(item)
  }
}

meanwhilefor...ofLoops can also be used with asynchronous code. That is, you can perform some asynchronous operations while traversing an iteratable object.for...ofThe loop will be asynchronous, allowing you to wait for the asynchronous operation to complete.

What needs to be remembered is where to use itawaitkeyword. You don’t need to put it in the loop, you should put it in the loopfor...ofKeywordsforThe back of the car. Now when you usenext()Method gets the next value of the asynchronous iteratorPromise. If you want to know more, you can check it out at GitHub(https://github.com/tc39/propo…)。

//Create an asynchronous function:
async function processResponses(someIterable) {
  //Iterate over the iteratable object and wait for the result of the asynchronous operation
  for await (let item of someIterable) {
    processItem(item)
  }
}

Rest / spread property

restandspreadIt’s not really a new feature. Both were introduced as new operators in ES6, and they soon became popular. JavaScript programmers love them, so to speak. The only problem is that they can only be used on arrays and parameters, but es2018 introduces these two functions into objects.

restandspreadThe syntax of the operator is very simple and consists of three points(...)Composition. These points are followed by the ones to be used onrestorspreadOperator. Next, let’s briefly discuss the working principle of the two.

Object

restOperator allows you to extract all the remaining object properties of an object to a new object. Note that these properties must be enumerable. If you’ve used decomposition for some attributes, thenrestThe operator extracts only the remaining attributes.

// Rest example:

const daysObj = {
  one: 'Monday',
  two: 'Tuesday',
  three: 'Wednesday',
  four: 'Thursday',
  five: 'Friday'
}

//Use deconstruction to assign the first two attributes of a variable to the variable.
//Rest is then used to assign the remaining attributes to a third variable.
const { one, two, ...restOfDays } = daysObj
//Rest only extracts "three", "four" and "Five" 
//Because we've extracted "one" and "two" 

console.log(one)
// Output:
// 'Monday'

console.log(two)
// Output:
// 'Tuesday'

console.log(restOfDays)
// Output:
// { three: 'Wednesday', four: 'Thursday', five: 'Friday' }

If you want to userestOperator, you need to remember two things: first, you can only use it once, unless you use it on nested objects. Second, it must be used in the end. That’s why in the example above, you see it after deconstructing the first two attributes instead of before.

//This line of code doesn't work because the rest operator is used first:
const { ...all, one, two } = { one: 1, two: 2, three: 3 }

//It works:
const { one, two, ...all } = { one: 1, two: 2, three: 3 }

//This line doesn't work because there are multiple rest operators at the same level:
const { one, ...some, ...end } = { /* some properties */ }

//This line works with multiple rest operators at multiple levels:
const { one, {...secondLevel }, ...firstLevel } = { /* some properties */ }

Object

The function of the spread operator is to create a new object by inserting all the properties of another object. The spread operator also allows you to insert properties from multiple objects. You can also use this operator in conjunction with adding new properties.

// Spread example:
const myOriginalObj = { name: 'Joe Doe', age: 33 }
//Create a new object with the spread operator:
const myNewObj = { ...myOriginalObj }

console.log(myNewObj)
// Output:
// { name: 'Joe Doe', age: 33 }


//Examples of adding attributes:
const myOriginalObj = { name: 'Caesar' }
//Creating new objects with the spread operator
//And add a new attribute "gene":
const myNewObj = { ...myOriginalObj, genre: 'Strategy' }

console.log(myNewObj)
// Output:
// {
//   name: 'Caesar',
//   genre: 'Strategy'
// }


//Spread operator and merge two objects:
const myObjOne = { title: 'Eloquent JavaScript' }
const myObjTwo = { author: 'Marijn Haverbeke' }

const myNewObj = { ...myObjOne, ...myObjTwo }

console.log(myNewObj)
// Output:
// {
//   title: 'Eloquent JavaScript',
//   author: 'Marijn Haverbeke'
// }

When inserting properties from multiple objects and adding new properties, order is important

Let me explain. Suppose you use the spread operator to create a new object based on two existing objects. The first existing object contains properties with some valuestitle. The second object also contains attributestitle, but the value is different. Which is the final choicetitle

The answer is the last one. If you use the spread operator on the first object and then on the second object, the secondtitleIt will take effect. If you permanent the spread operator on the second object, then the first objecttitleIt will take effect.

//Spread operator and merge two objects:
const myObjOne = {
  title: 'Eloquent JavaScript',
  author: 'Marijn Haverbeke',
}

const myObjTwo = {
  title: 'You Don\'t Know JS Yet',
  language: 'English'
}

//Using the spread operator to create a new object by combining "myobjone" and "myobjtwo"
//Note: the "title" in "myobjtwo" will override the "title" of "myobjtwo"
//Because "myobjtwo" comes last.
const myNewObj = { ...myObjOne, ...myObjTwo }

console.log(myNewObj)
// Output:
// {
//   title: "You Don't Know JS Yet",
//   author: 'Marijn Haverbeke',
//   language: 'English'
// }


//Note: the "title" in "myobjone" will override the "title" of "myobjtwo"
const myNewObj = { ...myObjTwo, ...myObjOne }

console.log(myNewObj)
// Output:
// {
//   title: 'Eloquent JavaScript',
//   language: 'English',
//   author: 'Marijn Haverbeke'
// }

Promise.prototype.finally()

There are two callback functions for promise at the beginning. One of them isthen()In the implementation of promise. The second iscatch()When promise is rejected orthen()Executed when an exception is thrown. Es2018 adds a third callback function for promisefinally()

Every time the promise is completed, it is executedfinally()Callback, regardless of whether the promise is complete or not. The general purpose of this callback is to perform operations that should always occur. For example, close the modal dialog box, close the database connection, or do some cleanup.

// finally() example:
fetch()
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.log(error))
  //Finally, do something:
  .finally(() => console.log('Operation done.'))

Improvement of regular expression

Es2018 also improves the regular expression function. These improvements include s (dotall) flag, trailing assertion, named capture group and Unicode attribute escape.

s(dotAll)

The first is s (dotall). And point(.)However, s (dotall) allows the matching of line breaks and emoticons.

// s(dotAll) example:
/hello.world/.test('hello\nworld')
// Output:
// false

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

Subsequent assertion

Before es2018, JavaScript only supportedAntecedent assertion. Antecedent assertions are used to match patterns based on subsequent text. Support for subsequent assertions has been added in es2018. It can match based on the text pattern before the pattern. The syntax of the trailing assertion is?<=

//Examples of subsequent assertions:
/(?<=green) apple/.test('One red apple is on the table.')
// Output:
// false

/(?<=green) apple/.test('One green apple is on the table.')
// Output:
// true

There is also a reverse backtracking after the assertion. This assertion matches the pattern only if there is no assertion before the substring. The syntax for negating a trailing assertion is?<!

/(?<!green) apple/.test('One red apple is on the table.')
// Output:
// true

/(?<!green) apple/.test('One green apple is on the table.')
// Output:
// false

Named capture group

Another good feature introduced to regular expressions by es2018 is to name capture groups. The syntax for naming capture groups is?<some_name>

const date_pattern = /(?<day>\d{2})\/(?<month>\d{2})\/(?<year>\d{4})/
const result = date_pattern.exec('11/12/2021')

console.log(result)
// Output:
// [
//   '11/12/2021',
//   '11',
//   '12',
//   '2021',
//   index: 0,
//   input: '11/12/2021',
//   groups: [Object: null prototype] { day: '11', month: '12', year: '2021' }
// ]

console.log(result.groups.day)
// Output:
// '11'

console.log(result.groups.month)
// Output:
// '12'

console.log(result.groups.year)
// Output:
// '2021'

Unicode property escape

Each Unicode character has many properties. For example: white space, case, letter, ASCII, emoticon, etc. Now you can access these properties in regular expressions.

There are two things you need to do to use this feature. First you have to use/uLogo. This flag tells JavaScript that your string is a series of Unicode code points. The second is to use\p{}. The property you want to check is between braces, otherwise use\P{}

//Create a string (Cyrillic) in Russian:
const myStrCyr = 'Доброе утро'

//Create English string (Latin alphabet)
const myStrLat = 'Good morning'

//Test whether "mystrcyr" contains Cyrillic characters:
/\p{Script=Cyrillic}/u.test(myStrCyr) // true

//Test whether "mystrlat" contains Cyrillic characters:
/\p{Script=Cyrillic}/u.test(myStrLat) // false

//Test whether "mystrlat" contains Cyrillic characters:
/\p{Script=Latin}/u.test(myStrCyr) // false

//Test whether "mystrlat" contains Latin characters:
/\p{Script=Latin}/u.test(myStrLat) // true

Four useful functions in es2018


This article starts with WeChat official account: front-end pioneer.

Welcome to scan the two-dimensional code to pay attention to the official account, and push you every day to send fresh front-end technical articles.

Four useful functions in es2018


Welcome to continue to read other high praise articles in this column: