Introduction to the

ES8 is a version released by the ECMA Association in June 2017. It is also called ES8 because it is the eighth version of ECMAScript.

Today we’ll cover the new features of ES8.

ES8 introduces two major features and four minor features, which we’ll cover next.

Async function

We mentioned generator in ES6, and Async functions operate much like generator.

Let’s look at Async in action:

//Async function definition:
async function foo() {}

//Async function expressions:
const foo = async function () {};

//Async method definition:
let obj = { async foo(){}}//Async arrow function:
const foo = async() = > {};Copy the code

The async function returns a wrapped Promise object:

async function asyncFunc() {
    return 123;
}

asyncFunc()
.then(x= > console.log(x));
    / / 123
Copy the code

If an exception is thrown in a function, reject Promise is thrown:

async function asyncFunc() {
    throw new Error('Problem! ');
}

asyncFunc()
.catch(err= > console.log(err));
    // Error: Problem!
Copy the code

In the example above we are using synchronous code in async function. If we want to execute asynchronous code in async, we can use await. Note that await can only be used in async.

Await followed by a Promise. If the Promise completes, then the result of the assignment of await is the Promise value.

If a Promise is rejected, await will throw an exception.

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

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

We can process the results of asynchronous execution 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);
    });
}
Copy the code

Asynchronous results can also be executed in parallel:

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);
    });
}
Copy the code

A final look at how to handle exceptions:

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

Note that if async returns something other than a Promise, it will be wrapped as a Promise. If it is already a Promise object, it will not be encapsulated again:

async function asyncFunc() {
    return Promise.resolve(123);
}
asyncFunc()
.then(x= > console.log(x)) / / 123
Copy the code

Similarly, if you return a Rejected Promise object, you get the same result as if you had thrown an exception:

async function asyncFunc() {
    return Promise.reject(new Error('Problem! '));
}
asyncFunc()
.catch(err= > console.error(err)); // Error: Problem!
Copy the code

If you just want to trigger an asynchronous method but don’t want to wait for it to finish, then don’t use await:

async function asyncFunc() {
    const writer = openFile('someFile.txt');
    writer.write('hello'); / / don 't wait
    writer.write('world'); / / don 't wait
    await writer.close(); // wait for file to close
}
Copy the code

Shared memory and atomic operations

ES7 introduces a new constructor, SharedArrayBuffer, and namespace Atomics.

In JS, in addition to the main thread, we can also create worker threads. The communication between the main thread and worker thread is carried out through the postMessage method.

But such communication is not efficient. Therefore, a shared space such as SharedArrayBuffer is introduced to improve message transmission efficiency.

// main.js

const worker = new Worker('worker.js');

// To be shared
const sharedBuffer = new SharedArrayBuffer( // (A)
    10 * Int32Array.BYTES_PER_ELEMENT); // 10 elements

// Share sharedBuffer with the worker
worker.postMessage({sharedBuffer}); // clone

// Local only
const sharedArray = new Int32Array(sharedBuffer); // (B)
Copy the code

In the above example, we created a SharedArrayBuffer and sent the SharedArrayBuffer to the worker via postMessage.

We know that postMessage sends messages as copies, but this is the correct way to use sharing.

Let me see how to receive this Buffer in worker:

// worker.js

self.addEventListener('message'.function (event) {
    const {sharedBuffer} = event.data;
    const sharedArray = new Int32Array(sharedBuffer); // (A)

    / /...
});
Copy the code

In worker, we encapsulate sharedBuffer with Int32Array and use it as Array.

So let’s consider a question. What problems can occur when using Share Buffer?

Because it is shared, it can be used simultaneously in multiple worker threads. If it is used at the same time, there will be the problem of multithreading sharing data, that is, the problem of concurrency.

To solve the concurrency problem, recall that Java specifically has a Concurrent package that contains Atomic classes that can perform Atomic operations.

In ES8, Atomics was also introduced to perform atomic operations on SharedArrayBuffer. Atomics also disables reordering.

Atomics Typed Array: Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array or Uint32Array.

Note that these arrays are all packaged arrays of SharedArrayBuffer. All arrays are Int arrays (currently only Int arrays are supported).

First, see how Atomics solves the problem of concurrent writes and reads of arrays:

Atomics.load(ta : TypedArray<T>, index) : T
Atomics.store(ta : TypedArray<T>, index, value : T) : T
Atomics.exchange(ta : TypedArray<T>, index, value : T) : T
Atomics.compareExchange(ta : TypedArray<T>, index, expectedValue, replacementValue) : T
Copy the code

Load and store can operate on TA as a whole.

Take a look at an example:

// main.js
console.log('notifying... ');
Atomics.store(sharedArray, 0.123);

// worker.js
while (Atomics.load(sharedArray, 0)! = =123);console.log('notified');
Copy the code

Atomics also provides Wait and Notity:

Atomics.wait(ta: Int32Array, index, value, timeout)
Atomics.wake(ta : Int32Array, index, count)
Copy the code

Wait causes the worker to wait on ta[index] when ta[index] is value.

Wake wakes the count of workers waiting on ta[index].

Atomics also provides a range of operations:

Atomics.add(ta : TypedArray<T>, index, value) : T
Atomics.sub(ta : TypedArray<T>, index, value) : T
Atomics.and(ta : TypedArray<T>, index, value) : T
Atomics.or(ta : TypedArray<T>, index, value) : T
Atomics.xor(ta : TypedArray<T>, index, value) : T
Copy the code

It is equivalent to:

ta[index] += value;
Copy the code

Atomic has a great use for building locks. We will cover this in a later article.

A new method for Object

Object provides two new methods for traversing entries and values.

Object.entries(value : any) : Array<[string,any]>
Copy the code

Entries return an array containing key-value pairs:

> Object.entries({ one: 1.two: 2[[})'one'.1 ], [ 'two'.2]]Copy the code

Entries give us a way to traverse Object:

let obj = { one: 1.two: 2 };
for (let [k,v] of Object.entries(obj)) {
    console.log(`The ${JSON.stringify(k)}: The ${JSON.stringify(v)}`);
}
// Output:
// "one": 1
// "two": 2
Copy the code

We can use entries to create maps:

let map = new Map(Object.entries({
    one: 1.two: 2,}));console.log(JSON.stringify([...map]));
    // [["one",1],["two",2]]
Copy the code

Similarly, Object also provides values methods:

Object.values(value : any) : Array<any>
Copy the code

Returns an array containing the value of Object.

In addition, the Object and a new method getOwnPropertyDescriptors.

This method returns a description of the property in Obj. The description of an attribute refers to whether the attribute is writable, countable and so on:

const obj = {
    [Symbol('foo')]: 123.get bar() { return 'abc'}};console.log(Object.getOwnPropertyDescriptors(obj));

// Output:
// { [Symbol('foo')]:
// { value: 123,
// writable: true,
// enumerable: true,
// configurable: true },
// bar:
// { get: [Function: bar],
// set: undefined,
// enumerable: true,
// configurable: true } }
Copy the code

Key is the key in Obj, value is PropertyDescriptors.

Although in ES6, Obj has introduced an object.assign () method to copy properties, this assign method can only copy properties with default values. For getters, setters, and non-writable properties with non-default values, object. assign cannot be copied. This time you need to use getOwnPropertyDescriptors method.

const source = {
    set foo(value) {
        console.log(value); }};console.log(Object.getOwnPropertyDescriptor(source, 'foo'));
// { get: undefined,
// set: [Function: foo],
// enumerable: true,
// configurable: true }

const target1 = {};
Object.assign(target1, source);
console.log(Object.getOwnPropertyDescriptor(target1, 'foo'));
// { value: undefined,
// writable: true,
// enumerable: true,
// configurable: true }
Copy the code

You can see that obj has a property foo, which is a setter. Therefore, you cannot copy using assign.

We look at how to use defineProperties and getOwnPropertyDescriptors copy:

const target2 = {};
Object.defineProperties(target2, Object.getOwnPropertyDescriptors(source));
console.log(Object.getOwnPropertyDescriptor(target2, 'foo'));
// { get: undefined,
// set: [Function: foo],
// enumerable: true,
// configurable: true }
Copy the code

In addition to copying properties, we can also copy objects:

const clone = Object.create(Object.getPrototypeOf(obj),
    Object.getOwnPropertyDescriptors(obj));
Copy the code

New method of String

String adds two new methods, padStart and padEnd.

Pad means fill, and we can fill it from the front or from the back. Let’s look at the use of pad:

String.prototype.padStart(maxLength, fillString=' ') 
String.prototype.padEnd(maxLength, fillString=' ') 
Copy the code

Take a look at the specific use:

> 'x'.padStart(5.'ab')
'ababx'
> 'x'.padEnd(5.'ab')
'xabab'
Copy the code

The comma can be added to the function argument list

Before ES8, you weren’t allowed to add a comma to the last argument of a function, but in ES8, everything is possible.

function foo(param1, param2,) {}
Copy the code

We can add a comma to the function definition. You can also add a comma to a function call:

foo(
    'abc'.'def',);Copy the code

Author: Flydean program stuff

This paper links: www.flydean.com/ecmascript-…

Source: Flydean’s blog

Welcome to pay attention to my public number: “procedures those things” the most popular interpretation, the most profound dry goods, the most concise tutorial, many you do not know the small skills you find!