1. Let and const commands

The let command is used to declare variables. Its use is similar to var, but the declared variable is only valid within the code block in which the let command resides.

{
  let a = 10;
  var b = 1;
}

a // ReferenceError: a is not defined.
b // 1Copy the code

Const declares a read-only constant. Once declared, the value of a constant cannot be changed.

Const PI = 3.1415; PI = 3; // TypeError: Assignment to constant variable.Copy the code

2. Destruct assignment of variables

Basic usage

ES6 allows you to extract values from arrays and objects and assign values to variables in a pattern called Destructuring.

Essentially, this is “pattern matching,” in which the variable on the left is assigned a corresponding value as long as the pattern on both sides of the equal sign is the same. Here are some examples of destructuring using nested arrays.

(1) Array deconstruction assignment

let [foo, [[bar], baz]] = [1The [[2].3]];
foo / / 1
bar / / 2
baz / / 3

let [ , , third] = ["foo"."bar"."baz"];
third // "baz"

let [x, , y] = [1.2.3];
x / / 1
y / / 3

let [head, ...tail] = [1.2.3.4];
head / / 1
tail / / [2, 3, 4]

let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z / / []Copy the code

(2) Object deconstruction assignment

Object deconstruction differs from arrays in one important way. The elements of an array are arranged in order, and the value of a variable is determined by its position. The attributes of an object have no order, and variables must have the same name as the attributes to get the correct value.

let { bar, foo } = { foo: "aaa".bar: "bbb" };
foo // "aaa"
bar // "bbb"

let { baz } = { foo: "aaa".bar: "bbb" };
baz // undefinedCopy the code

(3) Deconstruction and assignment of strings

Strings can also deconstruct assignments. This is because at this point, the string is converted to an array-like object

const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"Copy the code

(4) Deconstructive assignment of values and Boolean values

When deconstructing an assignment, if the value and Boolean are to the right of the equals sign, the object is converted first.

let {toString: s} = 123;
s === Number.prototype.toString // true

let {toString: s} = true;
s === Boolean.prototype.toString // trueCopy the code

(5) Deconstruction and assignment of function parameters

[[1.2], [3.4]].map(([a, b]) = > a + b);
// [3, 7]Copy the code
function add([x, y]){
  return x + y;
}

add([1.2]); / / 3Copy the code

3. String extensions

API:

  • CodePointAt () : Can correctly handle 4-byte stored characters and return a character code point

  • String.fromcodepoint () : Used to return corresponding characters from codepoints, but this method does not recognize 32-bit UTF-16 characters

  • At () : Returns a character at a given position in the string. This method cannot identify code points greater than0xFFFFThe word

  • Normalize () : Used to unify different representations of characters into the same form. This is called Unicode normalization.

  • Includes () : Returns a Boolean value indicating whether the parameter string was found.

  • StartsWith () : Returns a Boolean value indicating whether the parameter string is at the head of the source string

  • EndsWith () : Returns a Boolean value indicating whether the parameter string is at the end of the source string.

  • Repeat () : Returns a new string, indicating that the original string is repeatednTimes.

  • PadStart ()PadEnd () :If a string is not of a specified length, the header or tail is completed.padStartFor head completion,padEndUsed for tail completion.

(1) Unicode representation of characters

You can read the character correctly by putting the code point in braces.

"\u{20BB7}"
// "𠮷"

"\u{41}\u{42}\u{43}"
// "ABC"

let hello = 123;
hell\u{6F} // 123

'\u{1F680}'= = ='\uD83D\uDE80'
// trueCopy the code

(2) String traverser interface

ES6 adds a traverser interface to strings, making them available for… The of loop traverses.

for (let codePoint of 'foo') {
  console.log(codePoint)
}
// "f"
// "o"
// "o"
Copy the code

(3) Template string

The example code is as follows:

// A common character 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`);

// Embed variables in strings
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}? `Copy the code

4. Extension of re

(1) RegExp constructor

The first argument to the RegExp constructor is a regular object, so you can use the second argument to specify the modifier. Furthermore, the returned regular expression ignores the modifier of the original regular expression and uses only the newly specified modifier.

new RegExp(/abc/ig, 'i').flags
// "i"Copy the code

(2) String of regular method

There are four methods for string objects that can use regular expressions: match(), replace(), search(), and split().

ES6 uses these four methods to call RegExp instance methods within the language, so that all reged-related methods are defined on RegExp objects.

  • String.prototype.matchcallRegExp.prototype[Symbol.match]
  • String.prototype.replacecallRegExp.prototype[Symbol.replace]
  • String.prototype.searchcallRegExp.prototype[Symbol.search]
  • String.prototype.splitcallRegExp.prototype[Symbol.split]

(3) u modifier

  • Some characters

  • Unicode character representation

  • quantifiers

  • Predefined schema

  • The I modifier

5. Extension of ES6 values

Binary and octal notation

ES6 provides a new way to write binary and octal values, represented by prefixes 0b (or 0b) and 0O (or 0O), respectively.

API

  • Number.isFinite()

  • Number.isNaN()
  • Number.parseInt()
  • Number.parseFloat()
  • Number.isInteger()
  • Number.EPSILON

6. Array extensions

Array.from()

Used to turn two types of objects into true arrays: array-like objects and iterable objects (including the new ES6 data structures Set and Map).

Array.of()

Array.ofThe getValue () method converts a set of values to an array.

7. Function extension

ES6 allows you to set default values for function arguments, which are written directly after the parameter definition.

function log(x, y = 'World') {
  console.log(x, y);
}

log('Hello') // Hello World
log('Hello'.'China') // Hello China
log('Hello'.' ') // HelloCopy the code

(1) Arrow function

ES6 allows functions to be defined using arrows (=>).

var f = v => v; // is equal to var f is equal tofunction(v) {
 return v;
};
Copy the code

(2) Extended operators

The spread operator (spread) is three points (…) . It is like the inverse of the REST argument, turning an array into a comma-separated sequence of arguments.

console.log(... [1.2.3])
/ / 1 2 3

console.log(1. [2.3.4].5)
// 1, 2, 3, 4, 5

[...document.querySelectorAll('div')]
// [<div>, <div>, <div>]Copy the code

8. Object extension

(1) Concise representation of properties and methods

ES6 allows variables and functions to be written directly as properties and methods of objects. It’s much more concise.

var foo = 'bar';
var baz = {foo};
baz // {foo: "bar"}

/ / is equivalent to
var baz = {foo: foo};Copy the code

(2) Concise representation of the method

var o = {
  method() {
    return "Hello!"; }};/ / is equivalent to

var o = {
  method: function() {
    return "Hello!"; }};Copy the code

(3) the Object. The assign

The Object.assign method is used to merge objects. It copies all the enumerable attributes of the source Object to the target Object.

var target = { a: 1 };

var source1 = { b: 2 };
var source2 = { c: 3 };

Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}Copy the code

The object. assign method implements shallow copy, not deep copy. That is, if the value of an attribute of the source object is an object, the target object copies a reference to that object.

9, Symbol

The Symbol value is generated by the Symbol function. This means that object property names can now be of two types: the original string and the new Symbol type. Attribute names that belong to the Symbol type are unique and are guaranteed not to conflict with other attribute names.

10. Promise objects

Promise is a solution to asynchronous programming that makes more sense and is more powerful than traditional solutions — callback functions and events. It was first proposed and implemented by the community, and ES6 has written it into the language standard, unifying usage, and providing Promise objects natively.

A Promise is simply a container that holds the result of an event (usually an asynchronous operation) that will end in the future. Syntactically, a Promise is an object from which to get messages for asynchronous operations. Promise provides a uniform API, and all kinds of asynchronous operations can be handled in the same way.

Promise objects have two characteristics.

(1) The state of the object is not affected by the outside world. The Promise object represents an asynchronous operation and has three states: Pending, Resolved, and Rejected. Only the result of an asynchronous operation can determine the current state, and no other operation can change the state. That’s where the name “Promise” comes from. Its English name means “Promise,” indicating that nothing else can change it.

(2) Once the state changes, it will never change again, and this result can be obtained at any time. There are only two possibilities for a Promise object to change state: from Pending to Resolved and from Pending to Rejected. As long as those two things happen, the state is frozen, it’s not going to change, it’s going to stay the same. If the change has already occurred, you can add a callback to the Promise object and get the same result immediately. This is completely different from an Event, which is characterized by the fact that if you miss it and listen to it again, you will not get the result.

Basic usage

ES6 specifies that a Promise object is a constructor that generates a Promise instance.

The following code creates an instance of Promise.

var promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* Asynchronous operation succeeded */){
    resolve(value);
  } else{ reject(error); }});Copy the code

Once the Promise instance is generated, the THEN method can be used to specify the Resolved and Reject state callbacks, respectively.

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

Here is an example of loading images asynchronously.

function loadImageAsync(url) {
  return new Promise(function(resolve, reject) {
    var image = new Image();

    image.onload = function() {
      resolve(image);
    };

    image.onerror = function() {
      reject(new Error('Could not load image at ' + url));
    };

    image.src = url;
  });
}Copy the code

11. Set and MAP data structures

Basic usage of Set

S6 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.

The Set itself is a constructor used to generate the Set data structure

var s = new Set();

[2, 3, 5, 4, 5, 2, 2].map(x => s.add(x));

for (let i of s) {
  console.log(i);
}
// 2 3 5 4Copy the code

The purpose and basic usage of the Map structure

ES6 provides Map data structures. It is a collection of key-value pairs similar to objects, but the range of “keys” is not limited to strings. Values of all types (including objects) can be used as keys. In other words, the Object structure provides string-value mapping, and the Map structure provides value-value mapping, which is a more complete Hash structure implementation. If you need key-value data structures, Map is better than Object.

var m = new Map();
var o = {p: 'Hello World'};

m.set(o, 'content')
m.get(o) // "content"

m.has(o) // true
m.delete(o) // true
m.has(o) // falseCopy the code

12. Proxy and Reflect

Proxy

Proxy is used to modify the default behavior of certain operations, which is equivalent to making changes at the language level. Therefore, it is a kind of “meta programming”, that is, programming a programming language.

Proxy can be understood as a layer of “interception” before the target object. All external access to the object must pass this layer of interception. Therefore, Proxy provides a mechanism for filtering and rewriting external access. The word Proxy is used to mean that it acts as a Proxy for certain operations.

Proxy

Reflect objects, like Proxy objects, are a new API provided by ES6 for manipulating objects. The Reflect object is designed for several purposes.

(1) Put some methods of Object that are clearly internal to the language (such as Object.defineProperty) on Reflect. At this stage, some methods are deployed on both Object and Reflect objects, and future new methods will only be deployed on Reflect objects.

(2) Modify the return result of some Object methods to make them more reasonable. For example, Object.defineProperty(obj, name, desc) throws an error if the attribute cannot be defined, while Reflect.defineProperty(obj, name, desc) returns false.

// Try {object.defineProperty (target, property, attributes); // success} catch (e) {// failureif (Reflect.defineProperty(target, property, attributes)) {
  // success
} else {
  // failure
}Copy the code

13, Iterator and for… Of circulation

The concept of terator

In ES6, Map and Set are added to JavaScript’s original data structures that represent “collections”, mainly arrays and objects. There are four data sets, and users can combine them to define their own data structures, such as arrays whose members are Maps and maps whose members are objects. This requires a unified interface mechanism to handle all the different data structures.

An Iterator is one such mechanism. It is an interface that provides a unified access mechanism for various data structures. The Iterator interface can be deployed on any data structure to complete traversal (that is, processing all members of the data structure in turn).

Iterator provides a unified and simple interface for accessing various data structures. Second, the members of the data structure can be arranged in a certain order. Third, ES6 created a new traversal command for… The of loop is an Iterator interface for… Of consumption.

The Iterator traverses like this.

(1) Create a pointer object that points to the starting position of the current data structure. That is, the traverser object is essentially a pointer object.

(2) The first call to the next method of the pointer object can point to the first member of the data structure.

(3) The next call to the pointer object points to the second member of the data structure.

(4) Keep calling the next method of the pointer object until it points to the end of the data structure.

Each time the next method is called, information about the current member of the data structure is returned. Specifically, it returns an object containing both the value and done attributes. Where, the value attribute is the value of the current member, and the done attribute is a Boolean value indicating whether the traversal is complete.

Here is an example that simulates the return value of the Next method.

var it = makeIterator(['a'.'b']);

it.next() // { value: "a".done: false }
it.next() // { value: "b".done: false }
it.next() // { value: undefined, done: true }

function makeIterator(array) {
  var nextIndex = 0;
  return {
    next: function() {
      return nextIndex < array.length ?
        {value: array[nextIndex++], done: false} :
        {value: undefined, done: true}; }}; }Copy the code

for… Of circulation

ES6 uses C++, Java, C#, and Python to introduce for… The of loop, as a unified way to traverse all data structures.

A data structure that deploys the Symbol. Iterator attribute is considered to have an iterator interface. The of loop iterates through its members. That is to say, for… Inside the of loop is the symbol. iterator method of the data structure.

for… The scope of the of loop includes arrays, Set and Map structures, some array-like objects (such as Arguments objects, DOM NodeList objects), Generator objects, and strings.

The iterator interface is native to arrays (i.e. the Symbol. Iterator attribute is deployed by default), for… The of loop is essentially a traverser generated by calling this interface, as evidenced by the following code.

const arr = ['red'.'green'.'blue'];

for(let v of arr) {
  console.log(v); // red green blue
}

const obj = {};
obj[Symbol.iterator] = arr[Symbol.iterator].bind(arr);

for(let v of obj) {
  console.log(v); // red green blue
}Copy the code

14, the Generator/yield

Generator functions are an asynchronous programming solution provided by ES6 with completely different syntactic behavior from traditional functions

Generator functions can be understood in many ways. Syntactically, the Generator function is a state machine that encapsulates multiple internal states.

Execution of Generator returns an traverser object, that is, Generator is also a traverser object Generator in addition to the state machine. A traverser object that iterates through each state within the Generator in turn.

Formally, a Generator function is an ordinary function, but has two characteristics. There is an asterisk between the function keyword and the function name. Second, inside the function body, use yield statements to define different internal states (yield statements in English mean “output”).

function* helloWorldGenerator() {
  yield 'hello';
  yield 'world';
  return 'ending';
}

var hw = helloWorldGenerator();Copy the code

The above code defines a Generator function helloWorldGenerator with two yield statements “hello” and “world” inside, that is, the function has three states: the Hello, world, and return statements (end execution).

Generator functions are then called with a pair of parentheses following the function name as normal functions. The difference is that when a Generator function is called, it does not execute, and instead of returning the result of the function’s operation, it returns a pointer to the internal state, which is the Iterator Object described in the previous chapter.

Next, the next method of the traverser object must be called to move the pointer to the next state. That is, each time the next method is called, the internal pointer executes from the head of the function or where it was last stopped until the next yield statement (or return statement) is encountered. In other words, the Generator functions are executed piecewise, the yield statement is a token to pause execution, and the next method can resume execution.

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

The code above calls the next method four times.

On the first invocation, the Generator function starts executing until the first yield statement is encountered. The next method returns an object whose value property is the value of the current yield statement hello and the value of the done property false, indicating that the traversal is not finished.

On the second call, the Generator function executes from where the last yield statement left off until the next yield statement. The value property of the object returned by the next method is the current yield statement value world and the done property value false, indicating that the traversal has not finished.

On the third call, the Generator function executes from where the yield statement left off until the return statement (or the end of the function if there is no return statement). The value attribute of the object returned by the next method is the value of the expression immediately following the return statement (undefined if there is no return statement), and the value of the done attribute is true, indicating that the traversal is complete.

The next method returns the value of the object as undefined and the done property as true. Any subsequent calls to the next method will return this value.

To summarize, call the Generator function and return an traverser object representing an internal pointer to the Generator function. Each subsequent call to the next method of the traverser object returns an object with both value and done properties. The value property represents the value of the current internal state, which is the value of the expression following the yield statement; The done attribute is a Boolean value indicating whether the traversal is complete

Yield statements

Because the Generator returns a traverser object that only calls to the next method iterate over the next internal state, it actually provides a function to pause execution. The yield statement is the pause flag.

The next method of the traverser object runs as follows.

(1) When a yield statement is encountered, the following operation is paused and the value of the expression immediately following the yield is used as the value of the returned object’s value property.

(2) The next time the next method is called, the execution continues until the next yield statement is encountered.

(3) If no new yield statement is encountered, run until the end of the function until the return statement, and use the value of the expression following the return statement as the value of the returned object’s value property.

(4) If the function does not have a return statement, the value attribute of the returned object is undefined.

Note that the expression following the yield statement is executed only when the next method is called and an internal pointer points to the statement, thus providing JavaScript with manual “Lazy Evaluation” syntactic functionality.

function* gen() {
  yield  123 + 456;
}Copy the code

In the above code, the expression 123 + 456 following yield is not evaluated immediately, but only when the next method moves the pointer to this line.

There are similarities and differences between yield statements and return statements. The similarity is that you can return the value of the expression immediately following the statement. The difference is that at each yield, the function suspends execution and continues backward from that location the next time, whereas a return statement does not have location memory. A function can execute only one return statement (or one return statement), but can execute multiple yield statements (or more). A normal function can only return one value because it can only return once; Generator functions can return a series of values because there can be any number of yields. Another way of looking at it is to say that Generator generates a set of values, which is where its name comes from (in English, the word Generator means “Generator”)

Async and await

ES7 provides async functions to facilitate asynchronous operations. What is async function? In short, async functions are syntactic sugar for Generator functions.

Read two files in turn.

var fs = require('fs');

var readFile = function (fileName) {
  return new Promise(function (resolve, reject) {
    fs.readFile(fileName, function(error, data) {
      if (error) reject(error);
      resolve(data);
    });
  });
};

var gen = function* (){
  var f1 = yield readFile('/etc/fstab');
  var f2 = yield readFile('/etc/shells');
  console.log(f1.toString());
  console.log(f2.toString());
};Copy the code

I’m going to write async as a function, which looks like this

var asyncReadFile = async function (){
  var f1 = await readFile('/etc/fstab');
  var f2 = await readFile('/etc/shells');
  console.log(f1.toString());
  console.log(f2.toString());
}Copy the code

A comparison shows that an async function simply replaces the asterisk (*) of a Generator function with async, yields with await, and nothing more.

The improvements of async over Generator are shown in the following four aspects

(1) Built-in actuators. Generator functions must be executed by an executor, hence the CO module, while async functions have their own executor. In other words, async functions are executed exactly like normal functions, with only one line.

(2) Better semantics. Async and await are semantic clearer than asterisks and yield. Async means that there is an asynchronous operation in a function, and await means that the following expression needs to wait for the result.

(3) wider applicability. The CO module convention is that yield can only be followed by Thunk functions or Promise objects, while async functions can be followed by await commands with Promise objects and primitive values (numeric, string, and Boolean values, but this is equivalent to synchronous operations).

(4) Return the Promise. Async functions return a Promise object, which is much more convenient than Generator functions returning an Iterator. You can specify what to do next using the then method.

Further, async functions can be thought of as multiple asynchronous operations wrapped as a Promise object, and await commands are syntactic sugar for internal THEN commands.

16, Class

Developers familiar with pure object-oriented languages such as Java, Object-C, C #, etc., will have a special feeling for class. ES6 introduces classes, which make Object-Oriented programming of JavaScript easier and easier to understand.

Constructor (name,color) {this.name = name; // Class Animal {// Constructor, which will be called when instantiated, will have a default constructor with no arguments if not specified. this.color = color; } // toString is an attribute on the prototype objecttoString() {
      console.log('name:' + this.name + ',color:' + this.color);

    }
  }

 var animal = new Animal('dog'.'white'); // instantiate Animal animal.tostring (); console.log(animal.hasOwnProperty('name')); //true
 console.log(animal.hasOwnProperty('toString')); // false
 console.log(animal.__proto__.hasOwnProperty('toString')); // trueClass Cat extends Animal {constructor(action) {// Subclasses must constructor to specify the super function, // If consructor is not set, the default constructor with super will be added.'cat'.'white');
    this.action = action;
  }
  toString() {
    console.log(super.toString());
  }
 }

 var cat = new Cat('catch') cat.toString(); // Instance cat is an instance of cat and Animal, identical to Es5. console.log(cat instanceof Cat); //true
 console.log(cat instanceof Animal); // trueCopy the code

17. Module

ES5 does not support native modularity, and modules are added as an important part of ES6. The functions of the module are mainly composed of export and import. Each module has its own separate scope. The mutual call relationship between modules is to specify the interface exposed by the module through export, and to reference the interface provided by other modules through import. It also creates namespaces for modules to prevent function naming conflicts.

Export (export)

ES6 allows you to export multiple variables or functions in a module using export.

Export variables/constants

//test.js
export var name = 'Rainbow'
Copy the code

ES6 treats a file as a module that outputs a variable via export. A module can also output multiple variables simultaneously.

 //test.js
 var name = 'Rainbow';
 var age = '24';
 export {name, age};
Copy the code

The export function

// myModule.js
export function myModule(someArg) {
  return someArg;
} 
Copy the code

Import (import)

Once the output of a module is defined, it can be referenced by import in another module.

import {myModule} from 'myModule'; // main.js import {name,age} from'test'; // test.jsCopy the code

18. Decorators

A Decorator is a function that modifies the behavior of a class. This is a proposal for ES7, currently supported by Babel transcoder.

Modifiers change the behavior of classes at compile time, not run time. This means that the decorator can run the code at compile time.

Class of

function testable(target) {
  target.isTestable = true;
}

@testable
class MyTestableClass {}

console.log(MyTestableClass.isTestable) // trueCopy the code

The above code, @ testable is a decorator. It modifies the behavior of the MyTestableClass class by adding the static property isTestable to it.

Basically, the decorator behaves like this.

@ decorator class A {} / / is equivalent to A class A {} A = decorator (A) | | A;Copy the code

Method modification

class Person {
  @readonly
  name() { return `${this.first} ${this.last}`}}Copy the code

reference

ECMAScript® 2016 language standard

ECMAScript ® 2017