ES6 core features

  es6, Front end, html, javascript, Programmer

Preface

ES6 provides many new features, but we don’t use them very often in our actual work. According to the 28 rule, we should devote 80% of our energy and time to the study of these 20% core features, and we will get great results with twice the result with half the effort! Writing articles is not easy, please support and pay attention!The starting address of this articleGitHub blog (including mind map)

I. Configuration of Development Environment

This section focuses on:Babel compiles ES6 syntax and how to use webpack to realize modularity.

1.babel

Why do you need babel?

ES6 offers many new features, but not all browsers can support them perfectly. The following figure is a list of compatibility of each browser with ES6 (taking export as an example)

export各个浏览器兼容性一览表

As can be seen from the above figure, some browsers are not very friendly to ES6. To solve the compatibility problem of ES6, many teams have developed a variety of syntax parsing and conversion tools (such as babel, jsx, traceur, etc.) to convert ES6 syntax we wrote into ES5, which is equivalent to acting as a translator between ES6 and browsers. among themBabelIs a widely used transcoder that can convert ES6 code into ES5 code for execution in an existing environment.

How to configure babel?

Node.js must be installed first, npm init must be run, and then package.json file will be generated.
 ·npm install --save-dev babel-core babel-preset-es2015 babel-preset-latest
 Create and configure the. babelrc file//stored in the root directory of the project, at the same level as node_modules.
 ·npm install -g babel-cli
 ·babel-version

Babel’s configuration file is. babelrc, which is stored in the root directory of the project. This file is used to set transcoding rules and plug-ins. The specific contents are as follows:

//.babelrc file
 {
 "presets": ["es2015", "latest"],
 "plugins": []
 }

Verify that the configuration was successful

Create. /src/index.js
 Content: [1,2,3]. map (item = > item+1);
 :: running babel./src/index.js

After operation, the following section is obtained, which indicates that babel has been successfully configured.

"use strict";
 [1, 2, 3].map(function (item) {
 return item + 1;
 });

2.webpack

Why use WebPack?

Nowadays, many web pages can actually be regarded as functional applications. They have complicated JavaScript codes and a lot of dependency packages, and mold-speeding tools came into being. Among them, webpack are very popular for their powerful functions.
The way the Webpack works is: take your project as a whole, through a given main file (e.g. index.js), the Webpack will find all the dependent files of your project from this file, process them with loaders, and finally package them into one (or more) JavaScript files recognizable by the browser.

How to configure webpack?

·npm install webpack babel-loader --save-dev
 Create and configure webpack.config.js//webpack.config.js files to be the same level as package.json
 Configure scripts in package.json
 Run npm start
//configure webpack.config.js uses babel to parse files ending in.js except node_modules
 module.exports = {
 entry: './src/index.js',
 output: {
 path: __dirname,
 filename: './build/bundle.js'
 },
 module: {
 rules: [{
 test: /\.js?  $/,
 exclude: /(node_modules)/,
 loader: 'babel-loader'
 }]
 }
 }
//configure scripts in package.json
 "scripts": {
 "start": "webpack",
 "test": "echo \"Error: no test specified\" && exit 1"
 }

Second, block-level scope

ES5 has only a global scope and a function scope (for example, we must wrap the code within the function to limit the scope), which leads to many problems:

Case 1: Inner variables cover outer variables

var tmp = new Date();
 function f() {
 console.log(tmp);  //undefined
 if (false) {
 var tmp = "hello world";
 }
 }

Case 2: Variable Leakage Becomes Global Variable

var s = 'hello';
 for (var i = 0;   i < s.length;  i++) {
 console.log(s[i]);
 }
 console.log(i);  // 5

ES6 provides let and const to replace var declaration variables. The new declaration method supports block-level scope represented by braces, which brings some benefits:

1. Function expression (IIFE) that no longer needs to be executed immediately
In ES5, we need to construct an immediate function expression to ensure that we do not pollute the global scope. In ES6, we can use simpler braces ({}), and then use const or let instead of var to achieve the same effect.

2. Closures in Cyclic Bodies No More Problems
In ES5, if there is a closure inside the loop and variables outside the closure are accessed, problems will arise. In ES6, you can use “let” to avoid problems.

3. Prevent duplicate declaration of variables
ES6 does not allow variables with the same name to be repeatedly declared with let or const in the same scope. This is very helpful to prevent the existence of repeatedly declared function expressions in different js libraries.

Third, the expansion of the array

1. Array.from (): Converts a pseudo array object or traversable object to a true array

If all the key names of an object are positive integers or zeros and have the length attribute, then this object is very much like an array, called a pseudo array. Typical pseudo arrays areThe arguments object of the function, as well as most DOM element sets, and strings.

...
 < button > test 1</button >
 <br>
 < button > test 2</button >
 <br>
 < button > test 3</button >
 <br>
 <script type="text/javascript">
 let btns = document.getElementsByTagName("button")
 console.log("btns",btns);  //Get a Pseudo Array
 btns.forEach(item=>console.log(item)) Uncaught TypeError: btns.forEach is not a function
 </script>

For pseudo arrays, there is no general method of arrays, and errors will occur when traversing directly. ES6 adds an Array.from () method to provide a clear and clear way to solve this requirement.

From (btns). foreach (item = > console.log (item)) converts pseudo arrays into arrays

2.Array.of(v1, v2, v3): converts a series of values into an array

When the new Array () constructor is called, depending on the type and number of parameters passed in, some different results will actually result, such as:

let items = new Array(2) ;
 console.log(items.length) ;  // 2
 console.log(items[0]) ;  // undefined
 console.log(items[1]) ;
let items = new Array(1, 2) ;
 console.log(items.length) ;  // 2
 console.log(items[0]) ;  // 1
 console.log(items[1]) ;  // 2

When the Array constructor is called with a single numeric parameter, the length property of the array is set to that parameter. If you call using multiple parameters (whether or not they are numeric types), these parameters will also become items of the target array. This behavior of arrays is confusing and risky because sometimes you may not pay attention to the type of parameters passed.

ES6 introduces the Array.of () method to solve this problem. The function of this method is very similar to Array constructor, but it does not lead to special results when using a single numerical parameter.The Array.of () method always creates an array that contains all the passed-in parameters, regardless of the number and type of parameters

let items = Array.of(1, 2);
 console.log(items.length);  // 2
 console.log(items[0]);  // 1
 console.log(items[1]);  // 2
 items = Array.of(2);
 console.log(items.length);  // 1
 console.log(items[0]);  // 2

Array.of basically can be used to replace Array () or newArray (), and there is no overload caused by different parameters, and their behavior is very uniform.

3. find () and findIndex () of array instances

The find method of the array instance to find the first qualified array member. Its argument is a callback function that all array members execute in turn until the first member with a return value of true is found and then the member is returned. If there are no eligible members, undefined is returned.

[1, 4, -5, 10].find((n) => n < 0) // -5

The findIndex method of an array instance is very similar to the find method, returning the position of the first qualified array member, or -1 if all members do not meet the condition.

[1, 5, 10, 15].findIndex(function(value, index, arr) {
 return value > 9;
 }) // 2

4. includes () of array instances

The Array.prototype.includes method returns a boolean value that indicates whether an array contains the given value. The second parameter of this method represents the starting position of the search, which defaults to 0. If the second parameter is negative, it indicates the position of the reciprocal. If it is larger than the array length (for example, the second parameter is -4, but the array length is 3), it will be reset to start from 0.

[1, 2, 3].includes(2)   // true
 [1, 2, 3].includes(3, -1);  // true
 [1, 2, 3, 5, 1].includes(1, 2);  // true

Before this method, we usually use the indexOf method of the array to check whether it contains a certain value. The indexOf method has two disadvantages.First, it is not semantic enough. Its meaning is to find the first occurrence position of the parameter value, so it is not intuitive to compare whether it is not equal to -1. Second, it uses strict equality operator (= = =) to judge, which will lead to misjudgment of NaN.

[NaN].indexOf(NaN) // -1
 [NaN].includes(NaN) // true

5. entries () keys () and values () for array instances

ES6 provides entries (), keys (), and values (), which are used to traverse arrays. They all return a traverser object and can be traversed using the for…of loop. the only difference is that keys () is the traversal of key names, values () is the traversal of key values, and entries () is the traversal of key-value pairs.

for (let index of ['a', 'b'].keys()) {
 console.log(index);
 }
 // 0
 // 1
 
 for (let elem of ['a', 'b'].values()) {
 console.log(elem);
 }
 // 'a'
 // 'b'
 
 for (let [index, elem] of ['a', 'b'].entries()) {
 console.log(index, elem);
 }
 // 0 "a"
 // 1 "b"

Four, arrow function

ES6 allows the use of “arrows” (= >) to define functions. It has two main functions: reducing the code and changing the direction of this. Next we will introduce in detail:

1. Code reduction

const double1 = function(number){
 return number * 2;  //ES5 writing
 }
 const double2 = (number) => {
 return number * 2;  //ES6 writing
 }
 const double4 = number => number * 2;  //can be further simplified

Remember to add brackets to multiple parameters

const double6 = (number,number2) => number + number2;

If there is more than one statement in the code block part of the arrow function, enclose them with braces and return them with return statements.

const double = (number,number2) => {
 sum = number + number2
 return sum;
 }

Since braces are interpreted as code blocks, theIf the arrow function returns an object directly, parentheses must be placed outside the object, otherwise an error will be reported..

//Report an error
 let getTempItem = id => { id: id, name: "Temp" };
 //Do not report
 let getTempItem = id => ({ id: id, name: "Temp" });

In addition, it has the advantage of simplifying callback functions.

//normal function writing
 [1,2,3].map(function (x) {
 return x * x;
 });
 //Arrow Function Writing
 [1,2,3].map(x => x * x);  //[1, 4, 9]

2. Change the direction of this

For a long time, this object in JavaScript language has been a headache problem. You must be very careful when using this object method. The arrow function “binds” this, to a large extent, solves this puzzle. Let’s look at an example first:

const team = {
 members:["Henry","Elyse"],
 teamName:"es6",
 teamSummary:function(){
 return this.members.map(function(member){
 Return `${member} belongs to the ${this.teamName} group `;  // this does not know who to point to
 })
 }
 }
 console.log(team.teamSummary());  //["Henry belongs to the undefined group ","Elyse belongs to the undefined group "]

There is another function embedded in the teamSummary function, which leads to the disorder of the internal direction of this.
How to modify it:

Method one, let self = this

const team = {
 members:["Henry","Elyse"],
 teamName:"es6",
 teamSummary:function(){
 let self = this;
 return this.members.map(function(member){
 Return `${member} belongs to ${self.teamName} group `;
 })
 }
 }
 console.log(team.teamSummary());  //["Henry belongs to es6 team ","Elyse belongs to es6 team "]

Method 2. bind function

const team = {
 members:["Henry","Elyse"],
 teamName:"es6",
 teamSummary:function(){
 return this.members.map(function(member){
 // this does not know who to point to
 Return `${member} belongs to the ${this.teamName} group `;
 }.bind(this))
 }
 }
 console.log(team.teamSummary());  //["Henry belongs to es6 team ","Elyse belongs to es6 team "]

Method 3. Arrow Function

const team = {
 members:["Henry","Elyse"],
 teamName:"es6",
 teamSummary:function(){
 return this.members.map((member) => {
 // this refers to the team object
 Return `${member} belongs to the ${this.teamName} group `;
 })
 }
 }
 console.log(team.teamSummary());  //["Henry belongs to es6 team ","Elyse belongs to es6 team "]

3. Use Attention Points

(1) this object in the function body is the object at the time of definition, not the object at the time of use.

(2) It cannot be used as a constructor, that is, the new command cannot be used, otherwise an error will be thrown.

(3) arguments object cannot be used, which does not exist in the function body. If you want to use, you can use rest parameters instead.

(4) The yield command cannot be used, so the arrow function cannot be used as the Generator function.

Rest parameters

ES6 introduces rest parameters (in the form of … variable names) to obtain redundant parameters of functions, thus eliminating the need to use arguments objects.

The variable that rest parameters match is an array, which puts extra parameters into the array.
Let’s give an example: how to implement a summation function?

Traditional writing:

function addNumbers(a,b,c,d,e){
 var numbers = [a,b,c,d,e];
 return numbers.reduce((sum,number) => {
 return sum + number;
 },0)
 }
 console.log(addNumbers(1,2,3,4,5));  //15

ES6 writing style:

function addNumbers(...numbers){
 return numbers.reduce((sum,number) => {
 return sum + number;
 },0)
 }
 console.log(addNumbers(1,2,3,4,5));  //15

It can also be used in combination with deconstruction assignment

var array = [1,2,3,4,5,6];
 var [a,b,...c] = array;
 console.log(a);  //1
 console.log(b);  //2
 console.log(c);  //[3, 4, 5, 6]

Rest parameters can also be combined with arrow functions

const numbers = (...nums) => nums;
 numbers(1, 2, 3, 4, 5)// [1,2,3,4,5]

Note: ① Each function can only declare one rest parameter at most, and the rest parameter must be the last parameter, otherwise an error is reported.

(2) ②rest parameter cannot be used in object literal setter

let object = {
 Set name(...value){ // reported an error.
 //Execute some logic
 }
 }

VI. Expansion Operator

The extension operator is most closely associated with the remaining parameters. The remaining parameters allow you to merge multiple independent parameters into an array. The extended operator allows an array to be partitioned and each item to be passed to the function as a separate parameter.

When used in front of a string or array, it is called an extension operator. Personally, it can be understood as the inverse operation of rest parameters, which is used to disassemble the array or string.. In some cases, functions are not allowed to pass in arrays, so it is very convenient to use expansion operators. If you don’t believe me, let’s look at an example: Math.max () method, which accepts any number of parameters and returns the maximum of them.

let value1 = 25,
 let value2 = 50;
 console.log(Math.max(value1, value2));  //    50

However, if you want to process the values in the array, how do you find the maximum value at this time? The Math.max () method does not allow you to pass in an array. In fact, you can add … to the array just like using rest parameters and pass it directly to Math.max ()

let values = [25,50,75,    100]
 //equivalent to console.log (math.max (25,50,75,100));
 console.log(Math.max(...values));  //100

Extension operators can also be mixed with other parameters

let values = [-25,-50,-75,-100]
 console.log(Math.max(...values,0));  //0

Extended Operators Disassemble Strings and Arrays

var array = [1,2,3,4,5];
 console.log(...array);  //1 2 3 4 5
 var str = "String";
 console.log(...str);  //S t r i n g

The splicing can also be realized

var defaultColors = ["red","greed"];
 var favoriteColors = ["orange","yellow"];
 var fallColors = ["fire red","fall orange"];
 console.log(["blue","green",...fallColors,...defaultColors,...favoriteColors]
 //["blue", "green", "fire red", "fall orange", "red", "greed", "orange", "yellow"]

VII. Deconstruction and Assignment-More Convenient Data Access

ES6 adds deconstruction, which is the process of decomposing a data structure into smaller parts.

1. Why is deconstruction useful?

In ES5 and earlier versions, many and similar codes were required to obtain information from objects or arrays and store specific data in local variables. For example:

var expense = {
 type: "es6",
 amount:"45"
 };
 var type = expense.type;
 var amount = expense.amount;
 console.log(type,amount);

This code extracts the type and amount values of the expense object and stores them on a local variable with the same name. Although this code looks simple, imagine that if there are a large number of variables to be processed, you must assign them one by one. And if a nested data structure needs to be traversed to find information, you may mine the entire structure for a little data.

This is why ES6 adds deconstruction to objects and arrays. When the data structure is broken down into smaller parts, it becomes much easier to extract the data you want.

2. Objects

In the previous example, if the method of object deconstruction is adopted, it is easy to obtain the type and amount values of expense objects.

const { type,amount } = expense;
 console.log(type,amount);

Let’s look at another example:

let node = {type:"Identifier",    name:"foo"},
 type = "Literal",name = 5;
 ({type,name}= node);  //Use deconstruction to assign different values
 console.log(type);  //    "Identifier"
 console.log(name);  //    "foo"

Note: You must wrap the deconstruction assignment statement in parentheses.This is because exposed curly braces are parsed into code block statements that are not allowed to appear to the left of the assignment operator (i.e., the equal sign). Parentheses indicate that the curly braces inside are not block statements but should be interpreted as expressions, thus allowing assignment operations to be completed.

Default value:
You can optionally define a default value to use when the specified attribute does not exist. To do this, you need to add an equal sign after the attribute name and specify the default value, like this:

let node = {
 type: "Identifier",
 name: "foo"
 };
 let {
 type,
 name,
 value = true
 } = node;
 console.log(type);  //    "Identifier"
 console.log(name);  //    "foo"
 console.log(value);  //    true

Deconstruction of nested objects:
Using syntax similar to the literal of an object, you can drill down into nested object structures to extract the data you want.

let node = {
 type: "Identifier",
 name: "foo",
 loc: {
 start: {
 line: 1,
 column: 1
 },
 end: {
 line: 1,
 column: 4
 }
 }
 };
 let { loc: { start }} = node;
 console.log(start.line);  //    1
 console.log(start.column);  //    1

The deconstruction mode in this example uses curly braces to indicate that the start attribute should be searched inside the loc attribute of the node object.

Deconstruction parameter that must pass value

function setCookie(name, value, {
 secure,
 path,
 domain,
 expires
 }) {
 //Code for Setting cookie
 }
 setCookie("type", "js");  //Report an error

Within this function, the name and value parameters are required, but secure, path, domain, and expires are not. By default, when a function is called, an error will be thrown if the parameter is not deconstructed and passed. As in the example above, if the setCookie does not pass the third parameter, an error will be reported. If the deconstruction parameter is optional, you can provide a default value for the deconstruction parameter to handle this error.

function setCookie(name, value, {
 secure,
 path,
 domain,
 expires
 } = {}) {}
 setCookie("type", "js");  //No error will be reported

3. Arrays

const names = ["Henry","Bucky","Emily"];
 const [name1,name2,name3] = names;
 console.log(name1,name2,name3);  //Henry Bucky Emily
 const [name,...rest] = names;  //Combine expansion operators
 console.log(rest);  //["Bucky", "Emily"]

Deconstruct with {} to return the number of arrays

const {length} = names;
 console.log(length);  //3

Array deconstruction can also be used in assignment contexts, but there is no need to wrap expressions in parentheses.. This is different from the agreement of object deconstruction.

let colors = ["red", "green", "blue"],
 firstColor = "black",
 secondColor = "purple";
 [firstColor, secondColor] = colors;
 console.log(firstColor);  //    "red"
 console.log(secondColor);  // "green"

Default value: Array Deconstruction Assignment also allows you to specify default values anywhere in the array. The default value is used when the item at the specified location does not exist or its value is undefined.

let colors = ["red"];
 let [firstColor, secondColor = "green"] = colors;
 console.log(firstColor);  //    "red"
 console.log(secondColor);  //    "green"

Match with rest parameters

The concat () method is often used in ES5 to clone arrays, for example:

//clone array in ES5
 var colors = ["red", "green", "blue"];
 var clonedColors = colors.concat();
 console.log(clonedColors);  //"[red,green,blue]"

In ES6, you can use the syntax of the remaining items to achieve the same effect

//clone array in ES6
 let colors = ["red", "green", "blue"];
 let [...clonedColors] = colors;
 console.log(clonedColors);  //[red,green,blue]

Next let’s look at an example: how to convert an array into an object

const points = [
 [4,5],
 [10,1],
 [0,40]
 ];
 //The expected data format is as follows. How to realize it?
 // [
 //   {x:4,y:5},
 //   {x:10,y:1},
 //   {x:0,y:40}
 // ]
 let newPoints = points.map(pair => {
 const [x,y] = pair;
 return {x,y}
 })
 //The following methods can also be used to make it easier.
 let newPoints = points.map(([x,y]) => {
 return {x,y}
 })
 console.log(newPoints);

Mixed deconstruction

const people = [
 {name:"Henry",age:20},
 {name:"Bucky",age:25},
 {name:"Emily",age:30}
 ];
 //es5 writing
 var age = people[0].age;
 console.log(age);
 //es6 Deconstruction
 const [age] = people;
 console.log(age);  //Deconstruct array {name:"Henry",age:20} for the first time
 const [{age}] = people;  //Deconstruct Object Again
 console.log(age);  //20

4. Attention

When using deconstruction to declare variables in conjunction with var, let, const, an initializer (i.e., the value to the right of the equal sign) must be provided. The following code throws syntax errors due to missing initializers:

var { type, name };  //syntax error!
 let { type, name };  //syntax error!
 const { type, name };  //syntax error!

Eight, template string (templatestring)

The template string is an enhanced version of the string, identified by reverse quotation marks (`). * * It can be used as a normal string, can be used to define a multi-line string, or embed variables in a string.
Variables and functions are embedded in the template string, and the variable name needs to be written in $ {}. **

let name = "Henry";
 function makeUppercase(word){
 return word.toUpperCase();
 }
 let template =
 `
 <h1>${makeUppercase('Hello')}, ${name}!  < /h1>// can store functions and variables
 < p > thank you for watching our video. ES6 provides us with many useful methods and syntax to traverse!  </p>
 <ul>
 <li>1</li>
 <li>2</li>
 <li>3</li>
 <li>4</li>
 <li>5</li>
 </ul>
 `;
 document.getElementById('template').innerHTML = template;

For another example, the ElementUI library is commonly used in work. When customizing a pop-up box, it is convenient to use template strings:

await this.$alert(
 ` < p><strong > confirm whether to upgrade $ {
 this.lectureName
 }</strong><br > (if the handout package already exists, please regenerate it after upgrading) < /p >`,
 {
 dangerouslyUseHTMLString: true
 }
 )

What is the difference between Class and traditional constructors

Conceptually speaking, JS before ES6 did not have the concept of “class” like other object-oriented languages. For a long time, people used the new keyword to construct objects through functions (also called constructors) as “classes”. Because JS does not support native classes but only simulates them through prototypes, various methods of simulating classes are very confusing compared with traditional object-oriented methods, especially when subclasses inherit the parent class and subclasses need to call the methods of the parent class, etc.
ES6 provides a writing method closer to the traditional language and introduces the concept of Class as a template for objects. The class keyword allows you to define a class.However, classes are only syntax sugar based on prototype-oriented object patterns..

Compare how classes are implemented in traditional constructors and ES6 respectively:

//Traditional constructor
 function MathHandle(x,y){
 this.x=x;
 this.y=y;
 }
 MathHandle.prototype.add =function(){
 return this.x+this.y;
 };
 var m=new MathHandle(1,2);
 console.log(m.add())
//class grammar
 class MathHandle {
 constructor(x,y){
 this.x=x;
 this.y=y;
 }
 add(){
 return this.x+this.y;
 }
 }
 const m=new MathHandle(1,2);
 console.log(m.add())

What is the connection between the two? In fact, the essence of the two is the same, but there is a difference in grammar and sugar writing. Grammatical sugar refers to a grammar added to a computer language, which has no influence on the function of the language but is more convenient for programmers to use. For example, the class grammar sugar here makes the program more concise and readable.

typeof MathHandle //"function"
 MathHandle===MathHandle.prototype.constructor //true

Contrast how inheritance is implemented in traditional constructors and ES6 respectively:

//Traditional constructor inheritance
 function Animal() {
 this.eat = function () {
 alert('Animal eat')
 }
 }
 function Dog() {
 this.bark = function () {
 alert('Dog bark')
 }
 }
 Dog.prototype = new Animal()// bind prototype to implement inheritance
 var hashiqi = new Dog()
 hashiqi.bark()//Dog bark
 hashiqi.eat()//Animal eat
//ES6 inheritance
 class Animal {
 constructor(name) {
 this.name = name
 }
 eat() {
 alert(this.name + ' eat')
 }
 }
 class Dog extends Animal {
 constructor(name) {
 Super(name) // with extend must have super, which represents the constructor of the parent class, that is, the constructor in Animal
 this.name = name
 }
 say() {
 alert(this.name + ' say')
 }
 }
 Const dog = new Dog ('husky')
 Dog.say()// husky say
 At the same time, it is also very important for the Chinese government to strengthen its cooperation with other countries.

Class can be inherited by Extensions keyword, which is much clearer and more convenient than ES5′ s inheritance by modifying prototype chain.

What is the difference between Class and traditional constructors

  • Class is more syntactically oriented
  • The Class implementation inheritance is easier to read and understand, and is more friendly to beginners.
  • The essence is grammar sugar, using prototype

X. Basic Use and Principle of Promise

In the JavaScript world, all code is executed by a single thread. Due to this “defect”, all network operations and browser events of JavaScript must be executed asynchronously.Promise is a solution for asynchronous programming, which is more reasonable and powerful than traditional solutions (callback functions and events).

回调地狱

The appearance of promise in ES6 has solved the problem well for us.Back to hellThe so-called callback hell refers to when too many asynchronous steps need to be executed step by step, or there are too many asynchronous operations in a function, a large number of nested callbacks will be generated at this time, making the code too deeply nested to be read and maintained. ES6 recognized this problem, and now the use of promise has perfectly solved this problem.

Promise principle

Once the state changes, it will not change again, and this result can be obtained at any time. There are only two possibilities for the state of the Promise object to change: from pending to fulfilled and from pending to rejected.Promise object initialization state is Pending; When resolve is called, it will be called by pending = > fullfilled; When reject is called, it will be rejected by pending => rejected. The specific process is shown in the following figure:

Promise原理

Use process of Promise

  1. An instance of new Promise and return
  2. When new Promise is passed in, the function has two parameters, resolve reject.
  3. Resolve on success and reject on failure.
  4. Then monitoring results
function loadImg(src){
 const promise=new Promise(function(resolve,reject){
 var img=document.createElement('img')
 img.onload=function(){
 resolve(img)
 }
 img.onerror=function(){
 reject()
 }
 img.src=src
 })
 Return promise// returns an instance of promise
 }
 var src="http://www.imooc.com/static/img/index/logo_new.png"
 var result=loadImg(src)
 result.then(function(img){
 The callback function when console.log (img.width)//resolved (successful)
 },function(){
 Log ("failed")//callback function when rejected
 })
 result.then(function(img){
 console.log(img.height)
 })

Promise makes code easier to maintain, writes asynchronous code like synchronous code, and makes business logic easier to understand.

Iterator and for…of cycle

JavaScript’s original data structure representing “Set” is mainly Array and Object, and ES6 adds Map and set. 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 various data structures.Any data structure can be traversed (i.e. all members of the data structure can be processed sequentially) as long as the Iterator interface is deployed..

1.Iterator’s role:

  • Provide a unified and simple access interface for various data structures;
  • So that members of the data structure can be arranged in a certain order
  • ES6 creates a new traversal command for…of loop, and Iterator interface is mainly used for…of consumption.

2. Native data with iterator interface (available for of traversal)

  • Array
  • set container
  • Map container
  • String
  • Arguments object for function
  • NodeList object
let arr3 = [1, 2, 'kobe', true];
 for(let i of arr3){
 console.log(i);  // 1 2 kobe true
 }
let str = 'abcd';
 for(let item of str){
 console.log(item);  // a b c d
 }
var engines = new Set(["Gecko", "Trident", "Webkit", "Webkit"]);
 for (var e of engines) {
 console.log(e);
 }
 // Gecko
 // Trident
 // Webkit

3. Comparison of several traversal methods

  • The FOOF loop supports not only arrays, most pseudo array objects, but also string traversal, as well as Map and Set object traversal.
  • The for in loop can traverse strings, objects, arrays, and cannot traverse Set/Map.
  • The forEach loop cannot traverse strings and objects, but can traverse Set/Map

XII. ES6 Modularization

ES6 realizes the module function on the level of language standard, and it is quite simple to realize, aiming at becoming a common module solution for browsers and servers.Its module function mainly consists of two commands: export and import. The export command is used to specify the module’s external interface, and the import command is used to input functions provided by other modules.

/* * definition module math.js **/
 var basicNum = 0;
 var add = function (a, b) {
 return a + b;
 };
 export { basicNum, add };
 /* * Reference module * */
 import { basicNum, add } from './math';
 function test(ele) {
 ele.textContent = add(99 + basicNum);
 }

As shown in the example above, when using the import command, the user needs to know the name of the variable or function to be loaded, otherwise it cannot be loaded. In order to provide convenience for users and enable them to load the module without reading the document, the export default command is used to specify the default output for the module.

// export-default.js
 export default function () {
 console.log('foo');
 }

The above code is a module file export-default.js, whose default output is a function.
When other modules load the module, the import command can specify any name for the anonymous function.

// import-default.js
 import customName from './export-default';
 customName();  // 'foo'

The import command of the above code can use any name to point to the method of export-default.js output, then you do not need to know the function name of the original module output.It should be noted that braces are not used after the import command.

If you think the article is of some help to you, welcome toMy GitHub blogThank you very much for your praise and attention.

Reference article

ES6 Notes (1): The “Defects” of javascript Improved by ES6

Five JavaScript “Defects” Improved in ES6

ECMAScript 6 getting started

In-depth understanding of ES6

Rest Parameters and Extension Operators for ES6