ES6 Core Feature
Foreword
Although ES6 provides many new features, we don’t use it frequently in our actual work. According to the 28th rule, we should spend 80% of our energy and time on the 20% core. Features, you will receive a miraculous effect with half the effort! Writing articles is not easy, please support and pay attention!
1. Development environment configuration
This part focuses on: babel compiles ES6 syntax, how to use webpack to achieve modularization.
1. babel
Why do you need babel?
ES6 offers many new features, but not all browsers support them perfectly. The following figure is a list of ES6 compatibility of each browser (take export as an example)
Some browsers are not very friendly to ES6. For the compatibility of ES6, many teams have developed a variety of syntax parsing and conversion tools (such as babel, jsx, traceur, etc.), which can be written by us. Converting ES6 grammar to ES5 is equivalent to being a translator between ES6 and the browser. Among them, Babel is a widely used transcoder that can convert ES6 code to ES5 code for execution in existing environments.
How to configure babel?
- First install node.js, run npm init, and then generate the package.json file
- 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 details 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);
- Run babel./src/index.js
After running, you get the following part, indicating that babel has been successfully configured
"use strict";
[1, 2, 3].map(function (item) {
return item + 1;
});
2.webpack
Why use WebPack?
Many of today's web pages can actually be regarded as feature-rich applications. They have complex JavaScript code and a lot of dependency packages. Modularization tools have emerged as the times require. Among them, webpack is powerful and deeply loved by people.
The way Webpack works is: take your project as a whole, through a given main file (eg: index.js), Webpack will start from this file to find all the dependent files of your project, use loaders to process them, and finally Packaged as one (or more) browser-recognized JavaScript files.
How to configure webpack?
- npm install webpack babel-loader --save-dev
- Create and configure webpack.config.js//webpack.config.js file at the same level as package.json
- Configure scripts in package.json
- Run npm start
//Configure webpack.config.js For files ending in .js, except for node_modules, use babel to parse
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"
}
2. Block-level scope
ES5 only has global scope and function scope (for example, we have to wrap code inside functions to limit scope), which leads to a lot of problems:
Case 1: Inner variable overrides outer variable
var tmp = new Date();
function f() {
console.log(tmp); //undefined
if (false) {
var tmp = "hello world";
}
}
Case 2: The variable leaks and becomes a 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 declare variables instead of var, and the new declaration supports block-level scoping with curly braces, which brings some benefits:
1. Immediately Executed Function Expression (IIFE) is no longer required
In ES5, we need to construct an immediately executed function expression to ensure that we do not pollute the global scope. In ES6, we can use simpler braces ({}) and use const or let instead of var to achieve the same effect.
2. The closure in the loop body is no longer a problem
In ES5, if a closure is generated in the loop body and access to variables outside the closure will cause problems. In ES6, you can use "let" to avoid problems.
3. Prevent repeated declaration of variables
ES6 does not allow repeated declaration of variables with the same name with let or const in the same scope. This is very helpful to prevent duplicate declarations of function expressions in different js libraries.
Third, the expansion of the array
1. Array.from() : Convert a pseudo-array object or traversable object to a true array
If all keys of an object are positive integers or zeros, and have a length property , then the object is much like an array and is called a pseudo-array. Typical pseudo-arrays are arguments objects for functions, and most sets of DOM elements, as well as 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 for arrays, and direct traversal will cause errors. ES6 adds the Array.from() method to provide a clear and clear way to solve this need.
Array.from(btns).forEach(item=>console.log(item)) converts pseudo-array to array
2.Array.of(v1, v2, v3) : Convert a series of values into an array
When calling the new Array( ) constructor, depending on the type and number of arguments passed in, it actually leads to some different results, for example:
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 array's length property is set to that parameter. If called with multiple arguments (numeric or not), those arguments also become the items of the target array. This behavior of arrays is confusing and risky, because sometimes the type of the passed parameter may not be taken care of.
ES6 introduced the Array.of( ) method to solve this problem. This method works very much like an Array constructor, but does not cause special results when using a single numeric parameter. The Array.of( ) method always creates an array of all passed arguments, regardless of the number and type of arguments :
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 can basically be used to replace Array() or newArray(), and there is no overload due to different parameters, and their behavior is very uniform.
3. find() and findIndex() for array instances
The find method of an array instance is used to find the first eligible array member. Its parameter is a callback function, and all array members execute the callback function in turn until the first member whose return value is true is found, and then the member is returned. Returns undefined if there are no eligible members.
[1, 4, -5, 10].find((n) => n < 0) // -5
The use of the findIndex method of an array instance is very similar to the find method, returning the position of the first eligible array member, or -1 if all members are not eligible.
[1, 5, 10, 15].findIndex(function(value, index, arr) {
return value > 9;
}) // 2
4. Array instance includes()
The Array.prototype.includes method returns a boolean value indicating 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 countdown, and if it is greater than the array length at this time (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 used the indexOf method of the array to check whether it contains a certain value. The indexOf method has two shortcomings. One is that it is not semantic enough. Its meaning is to find the first occurrence of the parameter value, so it is not intuitive enough to compare whether it is not equal to -1. Second, it uses the strict equality operator (===) internally for judgment, 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() for traversing arrays. They all return a traverser object, which can be traversed with a for...of loop. The only difference is that keys() is a traversal of key names, values() is a traversal of key values, and entries() is a traversal of key values. Right traversal.
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"
Fourth, the arrow function
ES6 allows defining functions using "arrows" (=>). It has two main functions: reducing code and changing this pointer. Next, we will introduce in detail:
1. Reduce the code
const double1 = function(number){
return number * 2; //ES5 writing
}
const double2 = (number) => {
return number * 2; //ES6 writing
}
const double4 = number => number * 2; // can be simplified further
Remember to add parentheses for multiple parameters
const double6 = (number,number2) => number + number2;
If the code block of an arrow function has more than one statement, enclose them in curly braces and return with a return statement .
const double = (number,number2) => {
sum = number + number2
return sum;
}
Since curly braces are interpreted as code blocks, if the arrow function returns an object directly, you must put parentheses around the object, otherwise an error will be reported .
// report error
let getTempItem = id => { id: id, name: "Temp" };
// do not report
let getTempItem = id => ({ id: id, name: "Temp" });
In addition, there is an advantage of simplifying the callback function
// 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 this to point
The this object in the JavaScript language has been a headache for a long time, and you must be very careful when using this in object methods. The arrow function "binds" this, which largely solves this problem. 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`; // I don't know who this should point to
})
}
}
console.log(team.teamSummary());//["Henry belongs to the undefined team", "Elyse belongs to the undefined team"]
There is another function embedded in the teamSummary function, which leads to the confusion of the internal this pointing.
How to modify it:
Method 1, 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 the ${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 doesn't know who to point to
return `${member} belongs to the ${this.teamName} team`;
}.bind(this))
}
}
console.log(team.teamSummary());//["Henry belongs to es6 team", "Elyse belongs to es6 team"]
Method three, arrow function
const team = {
members:["Henry","Elyse"],
teamName:"es6",
teamSummary:function(){
return this.members.map((member) => {
// this points to the team object
return `${member} belongs to the ${this.teamName} team`;
})
}
}
console.log(team.teamSummary());//["Henry belongs to es6 team", "Elyse belongs to es6 team"]
3. Notes on use
(1) The this object in the function body is the object where it is defined, not the object where it is used.
(2) It cannot be used as a constructor, that is, the new command cannot be used, otherwise an error will be thrown.
(3) You cannot use the arguments object, which does not exist in the function body. If you want to use it, you can use the rest parameter instead.
(4) The yield command cannot be used, so arrow functions cannot be used as Generator functions.
Five, rest parameters
ES6 introduced rest parameters (in the form of...variable name), which are used to get redundant parameters of functions, so that there is no need to use the arguments object.
The variable paired with the rest parameter is an array that puts the redundant parameters into the array.
Let's take 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:
function addNumbers(...numbers){
return numbers.reduce((sum,number) => {
return sum + number;
},0)
}
console.log(addNumbers(1,2,3,4,5));//15
Can also be combined with destructuring 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 will be reported.
- rest parameter cannot be used in object literal setter
let object = {
set name(...value){ //error
//Execute some logic
}
}
6. Spread operator
The most closely related to the rest parameter is the spread operator. The rest parameter allows you to combine multiple individual parameters into an array; the spread operator allows you to split an array and pass each item as a separate parameter to the function.
When used in front of a string or an array, it is called the spread operator. Personally, it can be understood as the inverse operation of the rest parameter, which is used to disassemble the array or string . Sometimes, functions do not allow arrays to be passed in. In this case, it is very convenient to use the spread operator. If you don’t believe it, let’s look at an example: the Math.max() method, which accepts any number of parameters and returns the maximum value.
let value1 = 25,
let value2 = 50;
console.log(Math.max(value1, value2)); // 50
But if you want to process the values in the array, how do you find the maximum value at this point? The Math.max() method doesn't allow you to pass in an array. Actually you can prepend ... to the array as you do with the rest parameter 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
The spread operator can also be mixed with other parameters
let values = [-25,-50,-75,-100]
console.log(Math.max(...values,0)); //0
Spread operator deconstructs 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
Can also be spliced
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"]
Seven, destructuring assignment ---- more convenient data access
ES6 added destructuring, which is the process of breaking a data structure into smaller parts.
1. Why is deconstruction useful?
In ES5 and earlier, getting information from objects or arrays and storing specific data in local variables required writing a lot of similar code. E.g:
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 in local variables with the same name. Although this code looks simple, imagine that if you have a large number of variables to process, you have to assign values to them one by one; and if you have a nested data structure to traverse to find information, you might dig through the whole for a little bit of data structure.
This is why ES6 adds destructuring to objects and arrays. Extracting the data you want from a data structure becomes much easier when you break it down into smaller pieces.
2. Object
In the previous example, if the method of object destructuring is used, it is easy to obtain the type and amount values of the expense object.
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 destructuring to assign different values
console.log(type); // "Identifier"
console.log(name); // "foo"
Note: You must wrap destructuring assignment statements in parentheses because exposed curly braces are parsed as code block statements, and block statements are not allowed to appear on the left-hand side of an assignment operator (i.e. the equal sign). Parentheses indicate that the inner curly braces are not block statements, but should be interpreted as expressions, allowing assignments to be completed.
Default value:
A default value can optionally be defined to be used if the specified property does not exist. To do this, add an equals sign to the property name and specify a 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
Nested object destructuring:
Using an object literal-like syntax, you can drill down into a nested object structure 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 destructuring pattern in this example uses curly braces to indicate that it should descend into the loc property of the node object to find the start property.
Destructuring parameters that must be passed by value
function setCookie(name, value, {
secure,
path,
domain ,
expires
}) {
// code to set the cookie
}
setCookie("type", "js");//Error
Within this function, the name and value parameters are required, but secure, path, domain, and expires are not. By default, calling a function without passing a value to the parameter destructuring throws an error. As in the above example, if setCookie does not pass the third parameter, an error will be reported. If the destructuring parameter is optional, it is possible to provide default values for the destructed parameter to handle such errors.
function setCookie(name, value, {
secure,
path,
domain ,
expires
} = {}) {}
setCookie("type", "js");//No error will be reported
3. Array
const names = ["Henry","Bucky","Emily"];
const [name1,name2,name3] = names;
console.log(name1,name2,name3);//Henry Bucky Emily
const [name,...rest] = names;//Combined with spread operator
console.log(rest);//["Bucky", "Emily"]
Use {} destructuring to return the number of arrays
const {length} = names;
console.log(length);//3
Array destructuring can also be used in assignment context, but does not require parentheses to wrap expressions . This is different from the conventions of object destructuring.
let colors = ["red", "green", "blue"],
firstColor = "black",
secondColor = "purple";
[firstColor, secondColor] = colors;
console.log(firstColor); // "red"
console.log(secondColor); // "green"
Default values : Array destructuring assignment also allows default values to be specified anywhere in the array. When the item at the specified position does not exist, or its value is undefined, then the default value will be used.
let colors = ["red"];
let [firstColor, secondColor = "green"] = colors;
console.log(firstColor); // "red"
console.log(secondColor);// "green"
Match with rest parameter
In ES5, the concat() method is often used to clone arrays, for example:
// clone the array in ES5
var colors = ["red", "green", "blue"];
var clonedColors = colors.concat();
console.log(clonedColors); //"[red,green,blue]"
In ES6, you can use the rest item syntax to achieve the same effect
// clone the 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 to an object
const points = [
[4,5],
[10,1],
[0,40]
];
//The expected data format is as follows, how to achieve 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}
})
// You can also do the following, which is easier
let newPoints = points.map(([x,y]) => {
return {x,y}
})
console.log(newPoints);
Hybrid 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 destructuring
const[age] = people;
console.log(age);//The first time to deconstruct the array {name:"Henry",age:20}
const [{age}] = people;//deconstruct the object again
console.log(age);//20
4. Notes
When destructuring is used with var, let, and const to declare a variable, an initializer (ie, the value to the right of the equal sign) must be provided. The following code all throws a syntax error due to missing initializers:
var { type, name }; // Syntax error!
let { type, name }; // Syntax error!
const { type, name }; // Syntax error!
Eight, template string (template string)
Template strings are enhanced versions of strings, denoted by backticks (`). It can be used as a normal string, it can also be used to define multi-line strings, or to embed variables in strings.
To embed variables and functions in the template string, you need to write the variable name 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 a lot of easy-to-use methods and syntax for traversal!</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 very convenient to use a template string:
await this.$alert(
`<p><strong>Confirm whether to upgrade ${
this.lectureName
}</strong><br>(If the handout kit already exists, please regenerate it after upgrading)</p>`,
{
dangerouslyUseHTMLString: true
}
)
9. What is the difference between Class and traditional constructors
Conceptually, there was no concept of "classes" in pre-ES6 JS like other object-oriented languages. For a long time, people used the new keyword to construct objects through functions (also called constructors) as "classes". Since JS does not support native classes, but only simulates through prototypes, various methods of simulating classes are very confusing compared to traditional object-oriented methods, especially when a subclass inherits the parent class and the subclass calls the parent class. method, etc. when required.
ES6 provides a writing method that is closer to traditional languages, and introduces the concept of Class (class) as a template for objects. With the class keyword, classes can be defined. But classes are just syntactic sugar for the prototype-based object-oriented pattern .
Compare how classes are implemented in traditional constructors and ES6:
//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 syntax
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 the syntax sugar is different. The so-called syntactic sugar refers to a certain grammar added to the computer language, which has no effect on the function of the language, but is more convenient for programmers to use. For example, the class syntax sugar here makes the program more concise and more readable.
typeof MathHandle //"function"
MathHandle===MathHandle.prototype.constructor //true
Compare how inheritance is implemented in traditional constructors and ES6:
//traditional constructor inheritance
function Animal() {
this.eat = function () {
alert('Animal eat')
}
}
function Dog() {
this.bark = function () {
alert('Dog bark')
}
}
Dog.prototype = new Animal()// Bind the prototype and implement inheritance
var hashqi = new Dog()
hashqi.bark()//Dog bark
hashqi.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) // If there is an extend, there must be 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
dog.eat()//Husky eat
Inheritance between classes can be achieved through the extends keyword, which is much clearer and more convenient than ES5's implementation of inheritance by modifying the prototype chain.
What is the difference between a Class and a traditional constructor
- Class is syntactically more in line with object-oriented writing
- Class implementation inheritance is more readable and understandable, and more friendly to beginners
- The essence is still syntactic sugar, using prototype
Ten, the basic use and principle of Promise
In the world of JavaScript, all code is executed in a single thread. Because of this "bug", all network operations in JavaScript, browser events, must be performed asynchronously. Promises are a solution to asynchronous programming that is more reasonable and more powerful than traditional solutions (callbacks and events).
The emergence of promises in ES6 has given us a good solution to the problem of callback hell . The 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. Produces a lot of nested callbacks, making the code too deeply nested to read and maintain. ES6 recognizes this problem, and now the use of promises solves this problem perfectly.
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. The initialization state of the promise object is pending; when resolve (success) is called, it will be pending => fulfilled; when reject (failure) is called, it will be pending => rejected .
Promise usage process
- An instance of new Promise and return
- A function needs to be passed in when new Promise, the function has two parameters of resolve reject
- Execute resolve on success and reject on failure
- then listen for 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//Return a promise instance
}
var src="http://www.rendc.com/static/img/index/logo_new.png"
var result=loadImg(src)
result.then(function(img){
The callback function when console.log(img.width)//resolved (success)
},function(){
console.log("failed")//callback function when rejected (failed)
})
result.then(function(img){
console.log(img.height)
})
Promises make code easier to maintain, write asynchronous code like synchronous code, and make business logic easier to understand.
Eleven, Iterator and for...of loop
JavaScript's original data structures that represent "collections" are mainly arrays and objects. ES6 adds Map and Set. This requires a unified interface mechanism to handle all the different data structures. Iterators are one such 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 (ie, process all members of the data structure in turn) as long as the Iterator interface is deployed .
1. The role of Iterator:
- Provide a unified and convenient access interface for various data structures;
- Enables members of a data structure to be arranged in a certain order
- ES6 created a new traversal command for...of loop, and the Iterator interface is mainly used for for...of consumption.
2. Native data with iterator interface (for of traversal)
- Array
- set container
- map container
- String
- the arguments object of the 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 for of 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, but not Set/Map
The forEach loop cannot traverse strings and objects, but can traverse Set/Map
12. ES6 modularity
At the level of language standards, ES6 implements the module function, and the implementation is quite simple, aiming to become a common module solution for browsers and servers. Its module function is mainly composed of two commands: export and import. The export command is used to specify the external interface of the module, and the import command is used to import the functions provided by other modules.
/** Define the 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 above example, 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. To make it easier for users to load modules without reading the documentation, 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 output by export-default.js, then you do not need to know the function name output by the original module. It should be noted that curly brackets are not used after the import command.