Summary of major ES6 updates

Summary of major ES6 updates

The main updates of ES6 (summary)

Description

This article is excerpted from Ruan Yifeng's " Introduction to ECMAScript 6 ", suitable for those who have not been exposed to ES6 and want to understand the main updates of ES6 but do not want to read the cumbersome documents. If you want to learn more, please go to es6.ruanyifeng.com/#README

  • Expression : variable declaration, destructuring assignment
  • Built-in objects : string expansion, numerical expansion, object expansion, array expansion, function expansion, regular expansion, Symbol, Set, Map, Proxy, Reflect
  • Statements and operations : Class, Module, Iterator
  • Asynchronous programming : Promise, Generator, Async

var let const

Variable destructuring assignment

Array structure assignment

let [a, b, c] = [ 1 , 2 , 3 ]; copy the code

Essentially, this writing belongs to "pattern matching", as long as the patterns on both sides of the equal sign are the same, the variable on the left will be assigned the corresponding value

If the deconstruction is not successful, the value of the variable is equal to

undefined
.

Destructuring assignment allows default values to be specified.

let [foo = true ] = []; foo //true let [x, y = 'b' ] = [ 'a' ]; //x='a', y='b' let [x, y = 'b' ] = [ 'a' , undefined ]; // Copy code

Object destructuring assignment

There is an important difference between object destructuring and arrays. The elements of the array are arranged in order, and the value of the variable is determined by its position; and the properties of the object have no order, and the variable must have the same name as the property in order to get the correct value.

let {foo, bar} = { foo : 'aaa' , bar : 'bbb' }; foo //"aaa" bar //"bbb" Copy the code

Function parameters can also use destructuring assignment and can use default values

function move ( {x = 0 , y = 0 } = {} ) { return [x, y]; } move({ x : 3 , y : 8 }); //[3, 8] move({ x : 3 }); //[3, 0] move({}); //[0, 0] move (); //[0, 0] copy the code

Application scenario

  • Exchange the value of a variable
  • Return multiple values from a function
  • Definition of function parameters
  • Extract JSON data
  • Default value of function parameters
  • Traverse the Map structure
  • Specifying method of input module

String expansion

One ES6 enhanced support for Unicode

2. you can use for...of to loop through

3.template strings

  • The template string (template string) is an enhanced version of the string, identified with a backtick (`). It can be used as a normal string, it can also be used to define a multi-line string, or embed variable ${} in the string

  • Arbitrary JavaScript expressions can be placed inside the braces, operations can be performed, and object properties can be referenced.

  • Functions can also be called in the template string.

//Ordinary string `In JavaScript'\n' is a line-feed.` //Multi-line string `In JavaScript this is not legal.` console .log( `string text line 1 string text line 2` ); //string embedded variable the let name = "Bob" , Time = "Today" ; `the Hello $ {name} , How are you $ {Time} `? Copy the code

The function of the template string is not just the above. It can immediately follow the name of a function that will be called to process the template string. This is called the "tagged template" function.

Alert `hello` //equivalent to ALRT ([ 'Hello' ]) Copy the code

4.string adding method

  • includes() : returns a Boolean value, indicating whether the parameter string is found.

  • startsWith() : returns a Boolean value, indicating whether the parameter string is at the head of the original string.

  • endsWith() : returns a Boolean value, indicating whether the parameter string is at the end of the original string.

  • repeat
    The method returns a new string, which means that the original string is repeated
    n
    Times.

  • padStart()
    Used for head completion,
    padEnd()
    Used for tail completion.

  • trimStart()
    Eliminate spaces at the head of the string,
    trimEnd()
    Eliminate trailing spaces. They return new strings, and do not modify the original strings.

  • matchAll()
    The method returns all matches of a regular expression in the current string,

  • replaceAll()
    Method, you can replace all matches at once.

Numerical expansion

  • ES6 provides a new way of writing binary and octal values, using prefixes respectively
    0b
    (or
    0B
    )with
    0o
    (or
    0O
    ) Means.
  • Number.isNaN()
    Used to check whether a value is
    NaN
    .
  • Number.isFinite()
    Used to check whether a value is finite, that is, it is not
    Infinity
    .
  • ES6 will global approach
    parseInt()
    with
    parseFloat()
    , Transplanted to
    Number
    On the object, the behavior remains completely unchanged.
  • Number.isInteger()
    Used to determine whether a value is an integer.

Math object extension methods

  • Math.trunc
    The method is used to remove the decimal part of a number and return the integer part.
  • Math.sign
    The method is used to determine whether a number is positive, negative, or zero.
  • Math.cbrt()
    The method is used to calculate the cube root of a number.
  • Math.hypot
    The method returns the square root of the sum of squares of all parameters.

BigInt

All numbers in avaScript are stored as 64-bit floating-point numbers, which imposes two major limitations on the representation of values. One is that the precision of a value can only reach 53 binary digits (equivalent to 16 decimal digits). Integers larger than this range cannot be accurately represented by JavaScript, which makes JavaScript unsuitable for accurate scientific and financial calculations. The second is a value greater than or equal to 2 to the power of 1024, which JavaScript cannot represent, and will return

Infinity
.

ES2020 introduces a new data type BigInt (big integer) to solve this problem, which is the eighth data type of ECMAScript. BigInt is only used to represent integers, there is no limit on the number of digits, and integers of any number of digits can be accurately represented.

Function extension

Default parameters

function Point ( x = 0 , y = 0 ) { this .x = x; this .y = y; } const p = new Point(); P //{X: 0, Y: 0} copy the code

rest parameter

ES6 introduces rest parameters (in the form of

...variable name
), used to obtain the redundant parameters of the h function, so that you do not need to use
arguments
Object. The variable with the rest parameter is an array, and the variable puts the extra parameters into the array

function add ( ...values ) { let sum = 0 ; for ( var val of values) { sum += val; } return sum; } the Add ( 2 , . 5 , . 3 ) //10 duplicated code

name attribute

Functional

name
Property, which returns the function name of the function.

Arrow function

  • If the arrow function does not require parameters or requires multiple parameters, use a parenthesis to represent the parameter part.

  • If the arrow function has more than one statement in the code block, use curly braces to enclose them, and use

    return
    The statement returns.

  • If the arrow function returns an object directly, you must add parentheses outside the object, otherwise an error will be reported.

  • If the arrow function has only one line statement and does not need to return a value, there is no need to write curly braces.

//Normal function writing [ 1 , 2 , 3 ].map( function ( x ) { return x * x; }); //function written arrow [ . 1 , 2 , . 3 ] .map ( X => X * X); duplicated code

pay attention

(1) In the function body

this
The object is the object at the time of definition, not the object at the time of use.

(2) Cannot be used as a constructor, that is, cannot be used

new
Command, otherwise an error will be thrown.

(3) Not available

arguments
Object, the object does not exist in the function body. If you want to use it, you can use the rest parameter instead.

(4) Not available

yield
Command, so arrow functions cannot be used as generator functions.

Array expansion

Spread operator

The spread operator (spread) is three dots (

...
). It is like the inverse operation of the rest parameter, which converts an array into a sequence of parameters separated by commas.

  • The apply method of the replacement function

    Since the spread operator can expand the array, it is no longer needed

    apply
    Method, turn the array into a function parameter.

    //ES5 writing function f ( x, y, z ) { //... } var args = [ 0 , 1 , 2 ]; f.apply( null , args); //ES6 writing function f ( x, y, z ) { //... } let args = [ 0 , 1 , 2 ]; f(...args); Copy code
  • Copy array

const A1 = [ . 1 , 2 ]; //writing a const A2 = [A1 ...]; //writing two const [... A2] = A1; duplicated code
  • Merge array

    const arr1 = [ 'a' , 'b' ]; const arr2 = [ 'c' ]; const arr3 = [ 'd' , 'e' ]; //ES5 merged array arr1.concat(arr2, arr3); //['a','b','c','d','e'] //ES6 merged array [...arr1, ...arr2, ...arr3] //[ 'a', 'b ', 'c', 'd', 'e'] to copy the code
  • Combined with destructuring assignment (can only be placed in the last digit of the parameter)

    const [first, ...rest] = [ 1 , 2 , 3 , 4 , 5 ]; first //1 rest //[2, 3, 4, 5] const [first, ...rest] = []; first //undefined rest //[] const [first, ...rest] = [ "foo" ]; first //"foo" rest //[] const [... butLast, Last] = [ . 1 , 2 , . 3 , . 4 , . 5 ]; //given copy the code
  • Convert the array

    Any object that defines an Iterator interface (see the Iterator chapter) can be converted into a real array using the spread operator.

    New method

    • Array.from
      It is used to convert two types of objects into real arrays: array-like objects and iterable objects (including the new ES6 data structures Set and Map).
    • Array.of()
      Used to convert a set of values into an array
    • copyWithin()
      , In the current array, copy the member at the specified position to another position (it will overwrite the original member), and then return to the current array. In other words, using this method will modify the current array.
    • find
      , Used to find the first qualified array member.
    • findIndex
      , Returns the position of the first array member that meets the criteria, if all members do not meet the criteria, then return
      -1
      .
    • fill
      The method fills an array with the given value.
    • entries()
      ,
      keys()
      with
      values()
      Used to traverse the array. They all return a iterator object, you can use
      for...of
      Loop to traverse, the only difference is
      keys()
      Is the traversal of the key name,
      values()
      Is the traversal of the key value,
      entries()
      It is a traversal of key-value pairs.
    • Array.prototype.includes
      The method returns a boolean value indicating whether an array contains the given value
    • Array.prototype.flat()
      Used to "flatten" the nested array into a one-dimensional array

Object extension

Shorthand for object

let birth = '2000/01/01' ; const Person = { name : ' ' , //Same as birth: birth birth, //equivalent to hello: function ()... hello () { console .log( 'My name is' , this .name);} }; Copy code

Attribute name expression

let propKey = 'foo' ; let obj = { [propKey]: true , [ 'a' + 'bc' ]: 123 }; Copy code

name attribute

If the method of the object uses the value function (

getter
) And stored value function (
setter
),then
name
The attribute is not on the method, but the description object of the method s attribute
get
with
set
Above the attribute, the return value is the method name plus
get
with
set
.

const obj = { get foo () {}, set foo ( x ) {} }; obj.foo.name //TypeError: Cannot read property'name' of undefined const descriptor = Object .getOwnPropertyDescriptor(obj, 'foo' ); descriptor.get.name //"GET foo" descriptor.set.name //"the SET foo" Copy the code

Attribute traversal

(1) for...in

for...in
Loop through the object's own and inherited enumerable properties (excluding Symbol properties).

(2) Object.keys(obj)

Object.keys
Returns an array, including the key names of all enumerable properties (excluding Symbol properties) of the object itself (excluding inherited).

(3) Object.getOwnPropertyNames(obj)

Object.getOwnPropertyNames
Returns an array containing the key names of all the properties of the object itself (excluding Symbol properties, but including non-enumerable properties).

(4) Object.getOwnPropertySymbols(obj)

Object.getOwnPropertySymbols
Returns an array containing the keys of all Symbol properties of the object itself.

(5) Reflect.ownKeys(obj)

Reflect.ownKeys
Returns an array containing all the key names of the object itself (without inheritance), regardless of whether the key names are Symbol or string, and whether they are enumerable or not.

Chain judgment operator

const firstName = Message .body the .user .firstName ||??? 'default' ; const fooValue = myForm.querySelector ( 'INPUT [name = foo]' ) ?. value: undefined copy the code

The above code uses

?.
Operator, directly judge whether the object on the left is in the chain call
null
or
undefined
. If it is, do not go down again, but return
undefined
.

? ? Operator

Null judgment operator In order to avoid this situation, ES2020 introduces a new Null judgment operator

??
. It behaves like
||
, But only the value on the left side of the operator
null
or
undefined
When, the value on the right will be returned.

const the headerText response.settings.headerText = ?? 'the Hello, World!' ; const animationDuration response.settings.animationDuration ?? = 300 ; const ShowSplashScreen ?? = response.settings.showSplashScreen to true ; duplicated code

New method

  • Object.is
    Used to compare whether two values are strictly equal, basically the same as the behavior of the strict comparison operator (===).

  • Object.assign()
    The method is used to merge objects, copy all enumerable attributes of the source object (source) to the target object (target).

  • Object.getOwnPropertyDescriptors()
    The method returns an object. The attribute names of all the original objects are the attribute names of the object, and the corresponding attribute value is the description object of the attribute.

  • Object.setPrototypeOf
    The role of the method and
    The same is used to set the prototype of an object and return the parameter object itself. It is officially recommended by ES6 to set the prototype object.

  • Object.getPrototypeOf
    The prototype object used to read an object. The prototype object used to read an object.

  • Object.keys
    The method returns an array. The members are the keys of all enumerable properties of the parameter object itself (without inheritance).

  • Object.values
    The method returns an array. The members are the key values of all enumerable properties of the parameter object itself (without inheritance).

  • Object.entries()
    The method returns an array, the member is the key-value pair array of all enumerable properties of the parameter object itself (without inheritance).

  • Object.fromEntries()
    the way is
    Object.entries()
    The inverse operation of is used to convert an array of key-value pairs into an object.

Symbol

ES6 introduces a new primitive data type

Symbol
, Which represents a unique value.

Since each Symbol value is not equal, this means that the Symbol value can be used as an identifier for the attribute name of the object, and it can be guaranteed that there will be no attributes with the same name. This is very useful when an object is composed of multiple modules to prevent a certain key from being overwritten or overwritten accidentally.

let mySymbol = Symbol (); //The first way of writing let a = {}; a[mySymbol] = 'Hello!' ; //The second way of writing let a = { [mySymbol]: 'Hello!' }; //The third way of writing let a = {}; Object .defineProperty(a, mySymbol, { value : 'Hello!' }); //The above writing methods all get the same result a[mySymbol] //"Hello!" Copy the code

The above code uses the square bracket structure and

Object.defineProperty
, Assign the attribute name of the object as a Symbol value.

Set and Map

Set

ES6 provides a new data structure Set. It is similar to an array, but the values of the members are unique and there are no duplicate values.

Set
Itself is a constructor, used to generate Set data structure.

//remove duplicate member of an array of [... new new the Set (Array) Copy the code

Map

ES6 provides Map data structure. It is similar to an object and is also a collection of key-value pairs, but the scope of "keys" is not limited to strings. Various types of values (including objects) can be used as keys. In other words, the Object structure provides a "string-value" correspondence, and the Map structure provides a "value-value" correspondence, which is a more complete implementation of the Hash structure. If you need a "key-value pair" data structure, Map is more suitable than Object.

const m = new Map (); const o = { p : 'Hello World' }; m.set(o, 'content' ) m.get(o) //"content" m.has (O) //to true m.delete (O) //to true m.has (O) //to false copy the code

Proxy

Proxy is used to modify the default behavior of certain operations, which is equivalent to making changes at the language level, so it belongs to a kind of "meta programming" (meta programming), that is, programming a programming language.

Proxy can be understood as setting up a layer of "interception" before the target object. Any external access to the object must first pass through this layer. Therefore, it provides a mechanism to filter and rewrite external access. The original meaning of the word Proxy is proxy. It is used here to mean "proxy" certain operations, which can be translated as "proxy".

var obj = new Proxy ({}, { get : function ( target, propKey, receiver ) { console .log( `getting ${propKey} !` ); return Reflect .get(target, propKey, receiver); }, set : function ( target, propKey, value, receiver ) { console .log( `setting ${propKey} !` ); return Reflect .set(target, propKey, value, receiver); } }); Copy code

The above code sets up a layer of interception on an empty object and redefines the reading of attributes (

get
) And settings (
set
)behavior.

var proxy = new Proxy ({}, { get : function ( target, propKey ) { return 35 ; } }); proxy.time //35 proxy.name //35 proxy.title //35 copy the code

Web service client

The Proxy object can intercept any attributes of the target object, which makes it very suitable for writing Web service clients.

const service = createWebService( 'http://example.com/data' ); service.employees().then( json => { const employees = JSON .parse(json); // }); Copy code

The above code creates a new web service interface, which returns various data. Proxy can intercept any attribute of this object, so there is no need to write an adaptation method for each type of data, just write a Proxy to intercept it.

function createWebService ( baseUrl ) { return new Proxy ({}, { get ( target, propKey, receiver ) { return () => httpGet(baseUrl + '/' + propKey); } }); } Copy code

Reflect

Example: Using Proxy to implement observer mode

Observer mode refers to the function that automatically observes the data object. Once the object changes, the function will execute automatically.

const person = observable({ name : ' ' , age : 20 }); function print () { console .log( ` ${person.name} , ${person.age} ` ) } observe(print); PERSON.NAME = 'John Doe' ; //output //John Doe, 20 copy the code

In the above code, the data object

person
Is the observation objective, the function
print
Is the observer. Once the data object changes,
print
It will be executed automatically.

Next, use Proxy to write the simplest implementation of the observer pattern, which is to achieve

observable
with
observe
These two functions. The idea is
observable
The function returns a proxy of the original object, intercepts assignment operations, and triggers various functions that act as observers.

const queuedObservers = new Set (); const observe = fn => queuedObservers.add(fn); const observable = obj => new Proxy (obj, (set)); function set ( target, key, value, receiver ) { const result = Reflect .set(target, key, value, receiver); queuedObservers.forEach( observer => observer()); return result; } Copy code

In the above code, a

Set
Set, all observer functions are put into this set. then,
observable
The function returns the proxy of the original object, intercepting the assignment operation. Intercept function
set
Among them, all observers will be executed automatically.

Promise

Promise is a solution for asynchronous programming, which is more reasonable and more powerful than traditional solutions-callback functions and events

Features

(1) The state of the object is not affected by the outside world.

Promise
The object represents an asynchronous operation and has three states:
pending
(processing),
fulfilled
(Successful) and
rejected
(Failed). Only the result of the asynchronous operation can determine the current state, and no other operation can change this state. This is also
Promise
The origin of the name, its English meaning is "promise", which means that other means cannot be changed.

(2) Once the state changes, it will not change again, and this result can be obtained at any time.

Promise
There are only two possibilities for the state of the object to change: from
pending
Becomes
fulfilled
And from
pending
Becomes
rejected

use

ES6 regulations,

Promise
The object is a constructor, used to generate
Promise
Instance.

The following code creates a

Promise
Instance.

const promise = new Promise ( function ( resolve, reject ) { //... some code if ( /* Asynchronous operation succeeded*/ ){ resolve(value); } else { reject(error); } }); Copy code

Promise
The constructor accepts a function as a parameter, and the two parameters of the function are
resolve
with
reject
.

resolve
The function of the function is to
Promise
The status of the object changes from "unfinished" to "success" (that is, from pending to resolved), which is called when the asynchronous operation succeeds, and the result of the asynchronous operation is passed as a parameter;

reject
The function of the function is to
Promise
The state of the object changes from "incomplete" to "failed" (that is, from pending to rejected), which is called when the asynchronous operation fails, and the error reported by the asynchronous operation is passed as a parameter.

Promise
After the instance is generated, you can use
then
Methods are specified separately
resolved
Status and
rejected
The callback function of the state.

promise.then( function ( value ) { //success }, function ( error ) { //failure }); Copy code

then
The method can accept two callback functions as parameters. The first callback function is
Promise
The state of the object becomes
resolved
When called, the second callback function is
Promise
The state of the object becomes
rejected
When called. Both of these functions are optional and do not have to be provided. They all accept
Promise
The value passed by the object is used as a parameter.

Below is a

Promise
Simple examples of objects.

function timeout ( ms ) { return new Promise ( ( resolve, reject ) => { setTimeout (resolve, ms, 'done' ); }); } timeout( 100 ).then( ( value ) => { console .log(value); }); Copy code

In the above code,

timeout
Method returns a
Promise
An instance, which means a result that will only occur after a period of time. The specified time has passed (
ms
Parameters) later,
Promise
The status of the instance becomes
resolved
, It will trigger
then
The callback function bound to the method.

method

Promise.prototype.then()

Promise instance has

then
Method, that is,
then
Method is defined in the prototype object
Promise.prototype
Up. Its function is to add a callback function when the state of the Promise instance changes. As I said before,
then
The first parameter of the method is
resolved
The callback function of the state, the second parameter is
rejected
The callback function of the state, they are all optional.

Promise.prototype.catch()

Promise.prototype.catch()
the way is
.then(null, rejection)
or
.then(undefined, rejection)
The alias of is used to specify the callback function when an error occurs.

Promise.prototype.finally()

finally()
Methods are used to specify the operations that will be performed regardless of the final state of the Promise object. This method is the standard introduced by ES2018.

Promise.all()

Every success is successful, and if one fails, it fails.

const P = Promise .all ([P1, P2, P3]); Copy Code

In the above code,

Promise.all()
The method accepts an array as a parameter,
p1
,
p2
,
p3
They are all Promise instances, if they are not, they will be adjusted first
Promise.resolve
Method, the parameters are converted to Promise instances, and then processed further. In addition,
Promise.all()
The parameter of the method may not be an array, but it must have an Iterator interface, and each member returned is a Promise instance.

p
'S status is determined by
p1
,
p2
,
p3
The decision is divided into two situations.

(1) Only

p1
,
p2
,
p3
Status becomes
fulfilled
,
p
Will become
fulfilled
,at this time
p1
,
p2
,
p3
The return value is formed into an array and passed to
p
Callback function.

(2) As long as

p1
,
p2
,
p3
One of them is
rejected
,
p
The status becomes
rejected
, At this time the first one was
reject
The return value of the instance will be passed to
p
Callback function.

Promise.race()

Return to the first result

const P = Promise .race ([P1, P2, P3]); Copy Code

In the above code, as long as

p1
,
p2
,
p3
There is an instance that changes the state first,
p
The status changes accordingly. The return value of the Promise instance that changed first is passed to
p
Callback function.

Promise.allSettled()

Promise.allSettled()
The method accepts a set of Promise instances as parameters and wraps them into a new Promise instance. Only wait until all these parameter instances return results, whether it is
fulfilled
still is
rejected
, The packaging instance will end. This method was introduced by ES2020 .

Promise.any()

ES2021 introduced

Method . This method accepts a set of Promise instances as parameters and wraps them into a new Promise instance to return. As long as one of the parameter instances becomes
fulfilled
State, the packaging instance will become
fulfilled
Status; if all parameter instances become
rejected
State, the packaging instance will become
rejected
status.

Promise.resolve()

Return a

resolved
The state's Promise object.

Promise.reject()

Promise.reject(reason)
The method will also return a new Promise instance whose status is
rejected
.

Syntax of Generator function

The Generator function has many angles of understanding. Syntactically, it can be understood firstly that the Generator function is a state machine that encapsulates multiple internal states.

Executing the Generator function will return a iterator object, that is to say, in addition to the state machine, the Generator function is also a iterator object generation function. The returned iterator object can traverse each state in the Generator function in turn.

Formally, the Generator function is an ordinary function, but it has two characteristics. One is,

function
There is an asterisk between the keyword and the function name; the other is, the function body is used internally
yield
Expressions that define different internal states (
yield
It means "output" in English).

function * helloWorldGenerator () { The yield 'Hello' ; the yield 'World' ; return 'Ending' ; } var HW = helloWorldGenerator (); duplicated code

The above code defines a Generator function

helloWorldGenerator
, There are two
yield
expression(
hello
with
world
), that is, the function has three states: hello, world and return statement (end of execution).

Then, the calling method of the Generator function is the same as that of a normal function, adding a pair of parentheses after the function name. The difference is that after calling the Generator function, the function is not executed, and the return is not the result of the function, but a pointer to the internal state, which is the Iterator Object introduced in the previous chapter.

Next, you must call the iterator object

next
Method to move the pointer to the next state. In other words, every time you call
next
Method, the internal pointer is executed from the head of the function or where it stopped last time, until the next
yield
Expression (or
return
Statement). In other words, the Generator function is executed in stages,
yield
The expression is a token to suspend execution, and
next
The method can be resumed.

hw.next() //{value:'hello', done: false} hw.next() //{value:'world', done: false} hw.next() //{value:'ending', done: true} hw.next() //{value: undefined, done: true} copy the code

Async

async
The function returns a Promise object, you can use
then
Method to add a callback function. When the function is executed, once encountered
await
It will return first, wait until the asynchronous operation is completed, and then execute the statement behind the function body.

Below is an example.

async function getStockPriceByName ( name ) { const symbol = await getStockSymbol(name); const stockPrice = await getStockPrice(symbol); return stockPrice; } getStockPriceByName( 'goog' ).then( function ( result ) { console .log(result); }); Copy code

The above code is a function to get stock quotes, the front of the function

async
The keyword indicates that there is an asynchronous operation inside the function. When the function is called, it will immediately return a
Promise
Object.

The following is another example, specifying how many milliseconds to output a value.

function timeout ( ms ) { return new Promise ( ( resolve ) => { setTimeout (resolve, ms); }); } async function asyncPrint ( value, ms ) { await timeout(ms); console .log(value); } asyncPrint( 'hello world' , 50 ); Copy code

The above code specifies 50 milliseconds later, the output

hello world
.

due to

async
The function returns a Promise object, which can be used as
await
The parameters of the command. Therefore, the above example can also be written in the following form.

async function timeout ( ms ) { await new Promise ( ( resolve ) => { setTimeout (resolve, ms); }); } async function asyncPrint ( value, ms ) { await timeout(ms); console .log(value); } asyncPrint( 'hello world' , 50 ); Copy code

Return Promise object

async
The function returns a Promise object.

async
Inside the function
return
The value returned by the statement becomes
then
The parameter of the method callback function.

State changes of the Promise object

async
The Promise object returned by the function must wait until it is all inside
await
The Promise object after the command is executed before the state changes unless it encounters
return
Statement or throw an error. In other words, only
async
The asynchronous operation inside the function is executed before it is executed
then
The callback function specified by the method.

await command

Under normal conditions,

await
The command is followed by a Promise object, and the result of the object is returned. If it is not a Promise object, the corresponding value is returned directly.

async function f () { //equivalent to //return 123; return await 123 ; } F (). the then ( V => Console .log (V)) //123 duplicated code

Error handling

in case

await
An error occurs in the subsequent asynchronous operation, which is equivalent to
async
The Promise object returned by the function is
reject
.

async function f () { await new Promise ( function ( resolve, reject ) { throw new Error ( 'Error' ); }); } f() .then( v => console .log(v)) .catch ( E => Console .log (E)) //Error: the error copying the code

Iterator

JavaScript s original data structure representing "collections", mainly arrays (

Array
) And object (
Object
), ES6 added
Map
with
Set
. There are four types of data collections. Users can also combine them to define their own data structure. For example, the members of an array are
Map
,
Map
The members are objects. This requires a unified interface mechanism to handle all different data structures.

Iterator is such a mechanism. It is an interface that provides a unified access mechanism for a variety of different data structures. Any data structure can complete the traversal operation (that is, process all members of the data structure in turn) as long as the Iterator interface is deployed.

Iterator has three functions: one is to provide a unified and convenient access interface for various data structures; the other is to enable the members of the data structure to be arranged in a certain order; the third is that ES6 creates a new traversal command

for...of
Loop, the Iterator interface mainly provides
for...of
consumption.

Class

ES6

class
It can be seen as just a syntactic sugar, most of its functions, ES5 can do it, the new
class
The writing method just makes the writing method of the object prototype clearer and more like the syntax of object-oriented programming.

In the JavaScript language, the traditional method of generating instance objects is through constructors. Below is an example.

function Point ( x, y ) { this .x = x; this .y = y; } Point.prototype.toString = function () { return '(' + this .x + ', ' + this .y + ')' ; }; var P = new new Point ( . 1 , 2 ); duplicated code

The above code uses ES6

class
Rewrite it as follows.

class Point { constructor ( x, y ) { this .x = x; this .y = y; } toString () { return '(' + this .x + ', ' + this .y + ')' ; } } Copy code

The class must be called with new, otherwise an error will be reported. This is one of the main differences between it and the ordinary constructor, which can be executed without new.

(1) Strict mode

The internals of classes and modules are in strict mode by default, so there is no need to use

use strict
Specify the operating mode. As long as your code is written in a class or module, only strict mode is available. Considering that all future codes will actually run in modules, ES6 actually upgraded the entire language to strict mode

(2) There is no promotion

There is no hoist for classes, which is completely different from ES5.

(3) name attribute

Since in essence, ES6 classes are just a wrapper of ES5 constructors, many features of the functions are

Class
Inheritance, including
name
Attributes.

(4) Generator method

If a method is preceded by an asterisk (

*
), it means that the method is a Generator function.

(5) The point of this

If the method of the class contains

this
, It defaults to an instance of the class. However, you must be very careful, once you use this method alone, it is likely to report an error.

constructor()

constructor()
The method is the default method of the class, through
new
This method is automatically called when the command generates an object instance. A class must have
constructor()
Method, if not explicitly defined, an empty
constructor()
The method will be added by default.

Static methods and static properties

The class is equivalent to the prototype of the instance, and all methods defined in the class will be inherited by the instance. If before a method, add

static
The keyword means that the method will not be inherited by the instance, but will be called directly through the class, which is called a "static method". If the static method contains
this
Keywords, this
this
Refers to the class, not the instance.

ES6 clearly stipulates that there are only static methods and no static properties inside Class. There is now a proposal to provide static properties of the class, written in front of the instance properties, plus

static
Keywords.

Private methods and private properties

Currently, there is a proposal for

class
Added private attributes. The method is to use
#
Said.

Class inheritance

Inheritance of ES5 is essentially to create instance objects of subclasses first

this
, And then add the method of the parent class to
this
Above (
Parent.apply(this)
). The inheritance mechanism of ES6 is completely different. The essence is to first add the properties and methods of the parent instance object to
this
Above (so you must call
super
Method), and then use the subclass's constructor to modify
this
.

class ColorPoint extends Point { constructor ( x, y, color ) { super (x, y);//call the parent class constructor(x, y) this .color = color; } () { return this .color + '' + super .toString(); //call the toString() of the parent class } } Copy code

In the above code,

constructor
Methods and
toString
Among the methods, all appeared
super
Keyword, it represents the constructor of the parent class, used to create a new parent class
this

The subclass must be in

constructor
Method call
super
Method, otherwise an error will be reported when creating an instance. This is because the subclasses own
this
The object must be shaped first by the constructor of the parent class to obtain the same instance properties and methods as the parent class, and then process it, plus the subclass s own instance properties and methods. If you don't call
super
Method, the subclass will not get
this
Object.

Module

ES6 modules are not objects, but through

export
The command explicitly specifies the output code, and then passes
import
Command input.

export

//profile.js var firstName = 'Michael' ; var lastName = 'Jackson' ; var year = 1958 ; export {firstName, lastName, year }; //error function f () {} export f; //Correct export function f () {}; //correct function f () {} export {f}; copy code

import

//main.js import {firstName, lastName, year} from './profile.js' ; function setName ( element ) { element.textContent = firstName + '' + lastName; } Copy code

Of the above code

import
Command to load
profile.js
File and enter variables from it.
import
The command accepts a pair of braces, which specify the name of the variable to be imported from other modules. The variable name in the braces must be the same as the imported module (
profile.js
) The name of the external interface is the same.

export default

export default
The command is used to specify the default output of the module. Obviously, a module can only have one default output, so
export default
The command can only be used once. Therefore, there is no need to increase the brackets after the import command, because it can only be the only corresponding
export default
command.

Essentially,

export default
Is to output a file called
default
Variable or method, and the system allows you to give it any name

//The first group export default function crc32 () { //output //... } Import CRC32 from 'CRC32' ; //Input //The second group export function crc32 () { //output //... }; Import {CRC32} from 'CRC32' ; //input copy the code

Differences between ES6 and CommonJs

  • The output of the CommonJS module is a copy of the value, and the output of the ES6 module is the reference of the value.
  • The CommonJS module is loaded at runtime, and the ES6 module is the output interface at compile time.
  • CommonJS module
    require()
    Is the synchronous loading module, ES6 module
    import
    Commands are loaded asynchronously, and there is an independent parsing phase of module dependencies.

How to apply to coding practice

Block scope

It is recommended not to use

var
Command, instead use
let
Command supersedes.

in

let
with
const
Between, it is recommended to use first
const
, Especially in the global environment, variables should not be set, only constants should be set.

String

Static strings always use single quotes or back quotes, and do not use double quotes. Use backticks for dynamic strings.

//bad const a = "foobar" ; const b = 'foo' + a + 'bar' ; //acceptable const c = `foobar` ; //good const a = 'foobar' ; const b = `foo $(a) bar` ; copy the code

Destructuring assignment

When using array members to assign values to variables, destructuring assignment is preferred.

const arr = [ 1 , 2 , 3 , 4 ]; //bad const first = arr[ 0 ]; const second = arr[ 1 ]; Good// const [1. SECOND] = ARR; duplicated code

If the parameter of the function is a member of the object, destructuring assignment is preferred.

//bad function getFullName ( user ) { const firstName = user.firstName; const lastName = user.lastName; } //good function getFullName ( obj ) { const {firstName, lastName} = obj; } //best function getFullName ( {firstName, lastName} ) { } Copy code

If the function returns multiple values, the destructuring assignment of the object is preferred over the destructuring assignment of the array. This is convenient for adding return values later and changing the order of return values.

//bad function processInput ( input ) { return [left, right, top, bottom]; } //good function processInput ( input ) { return {left, right, top, bottom }; } const {left, right} = the processlnput (INPUT); duplicated code

Object

For objects defined in a single line, the last member does not end with a comma. For objects defined in multiple lines, the last member ends with a comma.

//bad const a = { k1 : v1, k2 : v2, }; const b = { k1 : v1, k2 : v2 }; //good const a = { k1 : v1, k2 : v2 }; const b = { k1 : v1, k2 : v2, }; Copy code

The object should be as static as possible. Once defined, no new attributes should be added at will. If adding attributes is unavoidable, use

Object.assign
method.

//bad const a = {}; ax = 3 ; //if reshape unavoidable const a = {}; Object .assign(a, { x : 3 }); //good const a = { x : null }; ax = 3 ; copy the code

If the attribute name of the object is dynamic, you can use the attribute expression definition when creating the object.

//bad const obj = { id : 5 , name : 'San Francisco' , }; obj[getKey( 'enabled' )] = true ; //good const obj = { id : 5 , name : 'San Francisco' , [getKey( 'enabled' )]: true , }; Copy code

In the above code, the object

obj
The last attribute name of, needs to be calculated. At this time, it is best to use the attribute expression, in the new
obj
When, define this attribute together with other attributes. In this way, all attributes are defined in one place.

In addition, try to use concise expressions for the attributes and methods of objects, so that they are easy to describe and write.

var ref = 'some value' ; //bad const atom = { ref : ref, value : 1 , addValue : function ( value ) { return atom.value + value; }, }; //good const atom = { ref, value : 1 , addValue ( value ) { return atom.value + value; }, }; Copy code

Array

Use the spread operator (...) to copy the array.

//bad const len = items.length; const itemsCopy = []; let i; for (i = 0 ; i <len; i++) { itemsCopy[i] = items[i]; } //good const itemsCopy = [...items]; Copy code

Use the Array.from method to convert an array-like object into an array.

const foo = Document .querySelectorAll ( '.foo' ); const Nodes = the Array .from (foo); duplicated code

function

The immediate execution function can be written in the form of an arrow function.

( () => { console .log( 'Welcome to the Internet.' ); })(); Copy code

Where anonymous functions are used as parameters, try to use arrow functions instead. Because it is more concise and binds this.

//bad [ 1 , 2 , 3 ].map( function ( x ) { return x * x; }); //good [ 1 , 2 , 3 ].map( ( x ) => { return x * x; }); Best// [ . 1 , 2 , . 3 ] .map ( X => X * X); duplicated code

Arrow function replace

Function.prototype.bind
, Should no longer use self/_this/that to bind this.

//bad const self = this ; const boundMethod = function ( ...params ) { return method.apply(self, params); } //acceptable const boundMethod = method.bind( this ); Best// const boundMethod = ( ... the params ) => method.apply ( the this , the params); duplicated code

For simple, one-line, non-reusable functions, arrow functions are recommended. If the function body is more complicated and the number of lines is large, you should still use the traditional function writing method.

All configuration items should be concentrated in one object and placed in the last parameter. Boolean values cannot be directly used as parameters.

//bad function divide ( a, b, option = false ) { } //good function divide ( a, b, {option = false } = {} ) { } Copy code

Don't use arguments variable in the function body, use rest operator (...) instead. Because the rest operator explicitly indicates that you want to get parameters, and arguments is an array-like object, and the rest operator can provide a real array.

//bad function concatenateAll () { const args = Array .prototype.slice.call( arguments ); return args.join( '' ); } //good function concatenateAll ( ...args ) { return args.join( '' ); } Copy code

Use default value syntax to set the default value of the function parameter.

//bad function handleThings ( opts ) { opts = opts || {}; } //good function handleThings ( opts = {} ) { //... } Copy code

Map structure

Pay attention to the distinction between Object and Map. Object is only used when simulating real-world physical objects. If you just need

key: value
The data structure uses the Map structure. Because Map has a built-in traversal mechanism.

let map = new Map (arr); for ( let key of map.keys()) { console .log(key); } for ( let value of map.values()) { console .log(value); } for ( let item of map.entries()) { console .log(item[ 0 ], item[ 1 ]); } Copy code

Class

Always use Class instead of operations that require prototype. Because Class is written more concisely and easier to understand.

//bad function Queue ( contents = [] ) { this ._queue = [...contents]; } Queue.prototype.pop = function () { const value = this ._queue[ 0 ]; this ._queue.splice( 0 , 1 ); return value; } //good class Queue { constructor ( contents = [] ) { this ._queue = [...contents]; } pop () { const value = this._queue[0]; this._queue.splice(0, 1); return value; } }

extends
instanceof

//bad const inherits = require('inherits'); function PeekableQueue(contents) { Queue.apply(this, contents); } inherits(PeekableQueue, Queue); PeekableQueue.prototype.peek = function() { return this._queue[0]; } //good class PeekableQueue extends Queue { peek() { return this._queue[0]; } }

Module JavaScript

import
require

//bad const moduleA = require('moduleA'); const func1 = moduleA.func1; const func2 = moduleA.func2; //good import { func1, func2 } from 'moduleA';

export
module.exports

//commonJS var React = require('react'); var Breadcrumbs = React.createClass({ render() { return <nav/>; } }); module.exports = Breadcrumbs; //ES6 import React from 'react'; class Breadcrumbs extends React.Component { render() { return <nav/>; } }; export default Breadcrumbs;

export default
export default
export default
export

export default

//bad import * as myObject from './importModule'; //good import myObject from './importModule';

function makeStyleGuide() { } export default makeStyleGuide;

const StyleGuide = { es6: { } }; export default StyleGuide;