Es7, es8 es9 new features


1. New ES7 features (ECMAScript 2016)

ES7 has two main additions to ES6:

  • Array. The prototype. Includes () method
  • Exponentiation operator (**)

Array. The prototype. Includes () method

The includes() method is used to determine whether an array contains a specified value, returning true if it does and false otherwise.

// ex
var array = [1.2.3];

console.log(array.includes(2));
// expected output: true

var pets = ['cat'.'dog'.'bat'];

console.log(pets.includes('cat'));
// expected output: true

console.log(pets.includes('at'));
// expected output: false
Copy the code

The array.prototype.includes () method takes two arguments:

  • The value to search for

  • The starting index of the search

When the second argument is passed in, the method searches backwards from the index (the default index value is 0). Return true if the search value exists in the array, false otherwise. Consider the following example:

// ex:
['a'.'b'.'c'.'d'].includes('b')         // true
['a'.'b'.'c'.'d'].includes('b'.1)      // true
['a'.'b'.'c'.'d'].includes('b'.2)      // false
Copy the code

For the difference with indexOf, see the code

/ / ex1:
var ary = [1];
if (ary.indexOf(1)! = =- 1) {
    console.log("Array exists 1")}if (ary.includes(1)) {
    console.log("Array exists 1")}/ / ex2:
var ary1 = [NaN];
console.log(ary1.indexOf(NaN))/ / 1
console.log(ary1.includes(NaN))//true

/ / ex3:
var ary1 = new Array(3);
console.log(ary1.indexOf(undefined));/ / 1
console.log(ary1.includes(undefined))//true

Copy the code

Exponentiation operator (**)

Addition/subtraction we usually use the infix form, which is straightforward. In ECMAScript2016, we can use ** instead of Math.pow.

4 ** 3           / / 64
/ / equivalent to the
Math.pow(4.3)

// It is worth mentioning that as an infix operator, ** also supports the following operations
let n = 4;
n **= 3;
/ / 64
Copy the code

2. New ES8 features (ECMAScript 2017)

Key new features:

  • Async Functions

Secondary new features:

  • Object.values / Object.entries
  • String padding
  • Object.getOwnPropertyDescriptors()
  • Function argument list and trailing comma in call

Async Functions

Async Functions are also called Async/Await. I believe everyone is familiar with this concept. Async/Await is a syntactic sugar for handling ASYNCHRONOUS JS operations that can help us get out of callback hell and write more elegant code.

Commonly understood, the async keyword is used to tell the compiler to treat calibrated functions differently. When the compiler encounters “await” keyword in the “await” function, it should stop running and wait until the “await” function has finished processing. If fulfiled, the function returns fulfillment Value, otherwise it gets Reject Value.

Here are a few common uses to make sense of them:

// ex:
async function asyncFunc() {
    const result = await otherAsyncFunc();
    console.log(result);
}

// Equivalent to:
function asyncFunc() {
    return otherAsyncFunc()
    .then(result= > {
        console.log(result);
    });
}

// The advantage is even greater when processing multiple asynchronous functions sequentially:
async function asyncFunc() {
    const result1 = await otherAsyncFunc1();
    console.log(result1);
    const result2 = await otherAsyncFunc2();
    console.log(result2);
}

// Equivalent to:
function asyncFunc() {
    return otherAsyncFunc1()
    .then(result1= > {
        console.log(result1);
        return otherAsyncFunc2();
    })
    .then(result2= > {
        console.log(result2);
    });
}
// parallel processing of multiple asynchronous functions:
async function asyncFunc() {
    const [result1, result2] = await Promise.all([
        otherAsyncFunc1(),
        otherAsyncFunc2(),
    ]);
    console.log(result1, result2);
}

// Equivalent to:
function asyncFunc() {
    return Promise.all([
        otherAsyncFunc1(),
        otherAsyncFunc2(),
    ])
    .then([result1, result2] => {
        console.log(result1, result2);
    });
}

// Handle error:
async function asyncFunc() {
    try {
        await otherAsyncFunc();
    } catch (err) {
        console.error(err); }}// Equivalent to:
function asyncFunc() {
    return otherAsyncFunc()
    .catch(err= > {
        console.error(err);
    });
}
Copy the code

Object.values and Object.entries

The object.values () method returns an array of all the enumerable property values of a given Object, in the same order as using for… The in loop has the same order (the difference is that for-In loops enumerate properties in the stereotype chain).

The obj parameter is the object to be operated on. It can be an object, or an array (an object with a numeric index, [10,20,30] -> {0: 10, 1:20, 2:30}).

// ex:
const obj = { x: 'xxx', y: 1 };
Object.values(obj); // ['xxx', 1]

const obj = ['e'.'s'.'8']; // equivalent to {0: 'e', 1: 's', 2: '8'};
Object.values(obj); // ['e', 's', '8']

// When we use numeric keys, we return numeric sort
// Sort by key
const obj = { 10: 'xxx'.1: 'yyy'.3: 'zzz' };
Object.values(obj); // ['yyy', 'zzz', 'xxx']

Object.values('es8'); // ['e', 's', '8']
Copy the code

The object. entries method returns an array of the given Object’s own traversable properties [key, value] sorted the same way as Object.values. The declaration of this method is trivial:

// ex:
const obj = { x: 'xxx', y: 1 };
Object.entries(obj); // [['x', 'xxx'], ['y', 1]]

const obj = ['e'.'s'.'8'];
Object.entries(obj); // [['0', 'e'], ['1', 's'], ['2', '8']]

const obj = { 10: 'xxx'.1: 'yyy'.3: 'zzz' };
Object.entries(obj); // [['1', 'yyy'], ['3', 'zzz'], ['10': 'xxx']]

Object.entries('es8'); // [['0', 'e'], ['1', 's'], ['2', '8']]
Copy the code

String padding

Added two functions to String: padStart and padEnd.

As their name suggests, the main purpose of these functions is to fill in the beginning and end of a string so that the resulting string length is the given length. You can fill it with a specific character, or a string, or a default space. Here is the declaration of the function:

str.padStart(targetLength [, padString])
str.padEnd(targetLength [, padString])
Copy the code

The first argument to these functions is targetLength, which is the length of the resulting string. The second argument is the optional padString (padding character), a string used to populate the source string. The default value is space.

'es8'.padStart(2);          // 'es8'
'es8'.padStart(5);          // ' es8'
'es8'.padStart(6.'woof');  // 'wooes8'
'es8'.padStart(14.'wow');  // 'wowwowwowwoes8'
'es8'.padStart(7.'0');     // '0000es8'

'es8'.padEnd(2);            // 'es8'
'es8'.padEnd(5);            // 'es8 '
'es8'.padEnd(6.'woof');    // 'es8woo'
'es8'.padEnd(14.'wow');    // 'es8wowwowwowwo'
'es8'.padEnd(7.'6');       // 'es86666'
Copy the code

Object.getOwnPropertyDescriptors

GetOwnPropertyDescriptors method returns the specified object all its attributes describe objects. Property description objects are defined directly on the object, rather than inheriting from the object’s stereotype. The main motivation for adding this function in ES2017 is to make it easy to deeply copy one object to another, and to copy getters/setters. The statement is as follows:

Object.getOwnPropertyDescriptors(obj)
Copy the code

Obj is the object to be operated on. The returned description object key values are different, Enumerable, writable, get, set and value.

const obj = { 
  get es7() { return 777; },
  get es8() { return 888; }};Object.getOwnPropertyDescriptors(obj);
/ / {
// es7: {
// configurable: true,
// enumerable: true,
// get: function es7(){}, //the getter function
// set: undefined
/ /},
// es8: {
// configurable: true,
// enumerable: true,
// get: function es8(){}, //the getter function
// set: undefined
/ /}
// }

Copy the code

At the end of a comma

The closing comma is very clear in code:

// When parameters are defined
function foo(param1, param2,) {}

// when a function is called
foo(
    'abc'.'def',);/ / object
let obj = {
    first: 'Jane',
    last: 'Doe'};/ / array
let arr = [
    'red'.'green'.'blue',];Copy the code

What are the benefits of this change?

  • First, it’s easier to rearrange items because you don’t have to add and remove commas if the last item changes its position.
  • Second, it helps version control systems track changes that actually occur. For example, from:
[
    'foo'
]

Copy the code

Modified to

[
    'foo'.'bar'
]

Copy the code

Causes line ‘foo’ and line ‘bar’ to be marked as changed, even though the only real change is when the latter line is added.

3, NEW ES9 features (ECMAScript 2018)

Key new features:

  • Asynchronous iterative
  • Rest/Spread properties

New regular expression features:

  • RegExp named capture groups
  • RegExp Unicode Property Escapes (Mathias Bynens)
  • RegExp Lookbehind Assertions

Other new features:

  • Promise.prototype.finally()
  • Template String modification

Asynchronous iterative

First, let’s review synchronous iterators:

ES6 introduces synchronous iterators, which work as follows:

  • Iterable: An object that represents the possibility of iterating through the symbol. iterator method.
  • Iterator: An object returned by calling iterable [symbol.iterator] (). It wraps each iteration element in an object and returns one at a time through its next() method.
  • IteratorResult: The object returned next(). The value attribute contains an iterated element, with the done attribute being the last element after true.

Example:

const iterable = ['a'.'b'];
const iterator = iterable[Symbol.iterator]();
iterator.next()
// { value: 'a'.done: false }
iterator.next()
// { value: 'b'.done: false }
iterator.next()
// { value: undefined, done: true }

Copy the code

Asynchronous iterator

The previous iteration approach was synchronous and did not apply to asynchronous data sources. For example, in the following code, readLinesFromFile() cannot pass its asynchronous data through synchronous iterations:


function readLinesFromFile (){
        setTimeout((a)= > {
            return "123456"
        },1000)}for (const line of readLinesFromFile()) {
    console.log(line);
}
function *createNumberIterator(){
        yield 1;
        yield 2;
        yield 3;
    }
    const iterator = createNumberIterator();
    const p2 = iterator.next(); // Object {value: 2, done: false}
    const p3 = iterator.next(); // Object {value: 3, done: false}
    const p4 = iterator.next(); // Object {value: undefined, done: true}
    const p1 = iterator.next(); // Object {value: 1, done: false}
    log(p1, p2, p3, p4)
Copy the code

Asynchronous iterators work much like regular iterators, but asynchronous iterators involve promises:

async function example() {
  // Common iterator:
  const iterator = createNumberIterator();
  iterator.next(); // Object {value: 1, done: false}
  iterator.next(); // Object {value: 2, done: false}
  iterator.next(); // Object {value: 3, done: false}
  iterator.next(); // Object {value: undefined, done: true}

  // Asynchronous iterator:
  const asyncIterator = createAsyncNumberIterator();
  const p = asyncIterator.next(); // Promise
  await p;// Object {value: 1, done: false}
  await asyncIterator.next(); // Object {value: 2, done: false}
  await asyncIterator.next(); // Object {value: 3, done: false}
  await asyncIterator.next(); // Object {value: undefined, done: true}
}
Copy the code

The next() method of an asynchronous iterator object returns a Promise that resolves like a regular iterator. Iterator.next ().then(({value, done})=> {//{value: ‘some val’, done: false}}

const promises = [
    new Promise(resolve= > resolve(1)),
    new Promise(resolve= > resolve(2)),
    new Promise(resolve= > resolve(3)),];async function test() {
    for await (const p of promises) {
        console.log(p);
    }
}
test(); / / 1, 2, 3
Copy the code

Rest/Spread properties

This is what is commonly referred to as REST parameters and extension operators. This feature was introduced in ES6, but objects in ES6 are limited to arrays

restParam(1.2.3.4.5);

function restParam(p1, p2, ... p3) {
  // p1 = 1
  // p2 = 2
  // p3 = [3, 4, 5]
}

const values = [99.100.- 1.48.16];
console.log( Math.max(... values) );/ / 100
Copy the code

In ES9, objects are provided with array-like REST arguments and extension operators:

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

function foo({a, ... param}) {
  console.log(a);    / / 1
  console.log(param) //{b: 2, c: 3}
}
Copy the code

Regular expressions name capture groups

A numbered capture group

// Regular expressions name capture groups
const RE_DATE = / [0-9] {4}) - ([0-9] {2}) - ([0-9] {2}) /;

const matchObj = RE_DATE.exec('1999-12-31');
const year = matchObj[1]; / / 1999
const month = matchObj[2]; / / 12
const day = matchObj[3]; / / 31
Copy the code

Capturing groups by digital reference has several disadvantages:

  • Finding the number of capture groups is a hassle: parentheses must be used.
  • If you want to understand what groups are for, you need to look at regular expressions.
  • If you change the order of the capture groups, you must also change the matching code.

Named capture group

In ES9, capture groups can be identified by name :(?

[0-9]{4})

Here, we mark the previous capture group year with a name. The name must be a valid JavaScript identifier (consider a variable name or attribute name). Once matched, you can access it by accessing the captured string matchobj.groups.year.

Let’s rewrite the previous code:

const RE_DATE = / (? 
      
       [0-9]{4})-(? 
       
        [0-9]{2})-(? 
        
         [0-9]{2})/
        
       
      ;

const matchObj = RE_DATE.exec('1999-12-31');
const year = matchObj.groups.year; / / 1999
const month = matchObj.groups.month; / / 12
const day = matchObj.groups.day; / / 31

// Destruct syntax is simpler
const {groups: {day, year}} = RE_DATE.exec('1999-12-31');
console.log(year); / / 1999
console.log(day); / / 31
Copy the code

You can see that naming capture groups has the following advantages:

  • It is easier to find the “ID” of the capture group.
  • The matching code becomes self-descriptive because the ID of the capture group describes what is being captured.
  • If you change the order of the capture groups, there is no need to change the matching code.
  • The names of the capture groups also make the regular expressions easier to understand because you can see directly what each group is used for.

Regular expression Unicode escape

This feature allows you to use \p{} to match characters by referring to Unicode character attributes inside braces, using the token U (Unicode) setting in regular expressions.

/^\p{White_Space}+$/u.test('\t \n\r')
// true
/^\p{Script=Greek}+$/u.test('mu epsilon tau ά')
// true
Copy the code

The new method matches Chinese characters

Since the Unicode Script for Chinese characters is Han, we can use this reg to match Chinese characters:

/[u4e00-u9fa5]/ [u4e00-u9fa5]/ [u4e00-u9fa5]/ [u4e00-u9fa5]/ [u4e00-u9fa5]

I randomly found a Chinese character “𬬭” added to Unicode8.0 on the Internet, and I tested the compatibility of the two regs:

oldReg=/[\u4e00-\u9fa5]/
newReg=/\p{Script=Han}/u

oldReg.test('abc')
// false
newReg.test('abc')
// false

oldReg.test(horizon)
// true
newReg.test(horizon)
// true

oldReg.test('𬬭')
// false
newReg.test('𬬭')
// true
Copy the code

Regular expression reverse assertion

Let’s see what regular expression preemptive assertions are:

For example, get the symbol of money

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

In ES9 it is possible to allow reverse assertions:

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

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

Promise.prototype.finally()

promise
  .then(result= >{...}). The catch (error= >{...}). Finally,(a)= > {···});
Copy the code

Finally callback is always executed. Note that.finally() is not executed after.then or.catch

Template String modification

ES2018 removes syntactic restrictions on ECMAScript escaping sequences in tagged template strings. Previously, \u started a Unicode escape, \x started a hexadecimal escape, and \ followed by a number started an octal escape. This makes it impossible to create specific strings, such as the Windows file path C:\uuu\ XXX \111.

To remove syntactic restrictions on escape sequences, use the markup function String.raw before the template String:

`\u{54}`
// "T"
String.raw`\u{54}`
// "\u{54}"
Copy the code

More front-end dry goods content in the “daily learning front” wechat public number, welcome to pay attention to

reference

  • The original document