ECMAScript 6 profile

ECMAScript 6.0 (ES6) is the next generation standard for the JavaScript language, which was officially released in June 2015. Its goal is to make JavaScript an enterprise-level development language that can be used to write complex, large-scale applications.

Let and const

Basic usage of let – block-level scope

In ES6, let can be used to declare variables, similar to var

⚠️ let declares variables that are valid only in the code block in which the let command resides

{
    let a = 10;
    var b = 20;
}
console.log(a); //a is not defined
console.log(b); / / 20
Copy the code

There is no variable promotion

The var command will promote the variable, that is, the variable can be used before the declaration and its value is undefined. This is somewhat strange, as normal logic dictates that variables should be used only after the statement has been declared.

To correct this, the let command changes the syntactic behavior so that the variable it declares must be used after the declaration or an error is reported

/ / var
console.log(c);/ / output is undefined
var c = 30;


/ / let's situation
console.log(c);/ / error ReferenceError
let c = 30;
Copy the code

Duplicate declarations are not allowed

Let does not allow the same variable to be declared twice in the same scope

let c = 10;
let c = 30;
console.log(c); / / an error

function func(arg) {
  let arg; / / an error
}
Copy the code

Temporary dead zone

The let and const commands declare the characteristics of variables.

The variable is not available within the code block until it is declared using the let command. This is grammatically called a temporal dead zone, or TDZ.

Why do you need block-level scopes?

Cause 1: Inner variables may overwrite outer variables
function foo(a){
    console.log(a);
    if(1= = =2) {var a = 'Hello Little Marco'; }}var a = 10;
foo(a);
Copy the code
Cause two: The loop traversal used to count is exposed as a global variable
var arr = []
for(var i = 0; i < 10; i++){
    arr[i] = function(){
        returni; }}console.log(arr[5] ());Copy the code

The variable I is used only to control the loop, but after the loop ends, it does not disappear. It is used for promotion and leaks into the global variable.

Solve loop counting problems

// Solution 1: Use closures
var arr = []
for(var i = 0; i < 10; i++){
    arr[i] = (function(n){
        
        return function(){
            return n;
        }
    })(i)
}
// Let declare I

var arr = []
for(let i = 0; i < 10; i++){
    arr[i] = function () {
        returni; }}Copy the code

Basic use of const – Declares a read-only constant

This means that a const, once declared, must be initialized immediately and cannot be left for later assignment. Const, declared without assigning, returns an error.

const a = 10;
a = 20;/ / an error

const b; / / an error
Copy the code

withletSimilarity of Commands

  • Block-level scope
  • Temporary dead zone
  • Non-repeatable declaration

letandconstUse advice

By default, const is used, and let is used only if you know that the value of the variable needs to be changed

Template string

In traditional JavaScript languages, output templates are written like this

const oBox = document.querySelector('.box');
// Template string
let id = 1,name = 'Little Pony';
let htmlTel = "<ul><li><p>id:" + id + "</p><p>name:" + name + "</p></li></ul>";
oBox.innerHTML = htmlTel;
Copy the code

This is rather cumbersome, and ES6 has introduced template strings to solve this problem

let htmlTel = `<ul>
    <li>
    <p>id:${id}</p>
    <p>name:${name}</p>
    </li>
</ul>`;
Copy the code

Deconstruction assignment

Deconstructing assignment is an extension of the assignment operator. It typically operates on arrays and objects.

Advantages: Concise code writing and high legibility

An array of deconstruction

Previously, to assign a value to a variable, you had to specify the value directly

let a = 1;
let b = 2;
let c = 3;
Copy the code

ES6 allows us to write:

let [a,b,c] = [1.2.3];
Copy the code

If the deconstruction fails, the value of the variable is equal to undefined

let [foo] = [];
let [bar, foo] = [1];
Copy the code

Foo will always be equal to undefined

Object to deconstruct

Deconstruction can be applied to objects

let node = {
    type:'identifier'.name:'foo'
}

let {type,name} = node;
console.log(type,name)//identifier foo
Copy the code

When destructively assigning an object, attributes can be ignored and residual operators used

let obj = {
    a: {name:'Joe'
    },
    b: [].c:'hello world'
}
// The b,c attributes are ignored
let {a} = obj;
The remainder operator uses this method to expand other attributes into an object store
let{a,... res} = obj;console.log(a,res);
Copy the code

The default value

let {a,b = 10} = {a:20};
Copy the code

Function argument destruct assignment

Go straight to the example

function add([x, y]){
  return x + y;
}

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

Use default values

function addCart(n,num=0){
    
    return n+num;
}
addCart(10);/ / 10
addCart(10.20); / / 30
Copy the code

use

  • Swap the values of variables

    let x = 1;
    let y = 2;
    let [x,y] = [y,x];
    Copy the code

    The above code exchanges the values of variables X and y, which is not only concise, but also easy to read, semantic very clear.

  • Returns multiple values from a function

    A function can return only one value. If you want to return multiple values, you must return them in arrays or objects. With deconstructing assignments, it’s very convenient to pull out these values.

    // Return an array
    
    function example() {
      return [1.2.3];
    }
    let [a, b, c] = example();
    
    // Return an object
    
    function example() {
      return {
        foo: 1.bar: 2
      };
    }
    let { foo, bar } = example();
    Copy the code
  • Definition of function parameters

    Destructuring assignments makes it easy to map a set of parameters to variable names.

    // Arguments are an ordered set of values
    function f([x, y, z]) {... } f([1.2.3]);
    
    // Arguments are an unordered set of values
    function f({x, y, z}) {... } f({z: 3.y: 2.x: 1});
    Copy the code
  • Extracting JSON data

    Destructuring assignments is especially useful for extracting data from JSON objects

    let jsonData = {
      id: 42.status: "OK".data: [867.5309]};let { id, status, data: number } = jsonData;
    // Find the property of the same name, and then assign it to the corresponding variable. It is the latter, not the former, that is really assigned
    console.log(id, status, number);
    // 42, "OK", [867, 5309]
    Copy the code
  • Default values for function arguments

  • Specifies the method of input module

    When a module is loaded, it is often necessary to specify which methods to input. Deconstructing assignment makes the input statement very clear.

    const {ajax} = require('xxx')
    
    ajax()
    Copy the code

Extension of a function

A function with default values for arguments

Before ES6, you could not specify default values for function parameters directly. You could only use workarounds

function log(x,y){
    y = y || 'world';
    console.log(x,y);
}
log('hello');//hello world
log('hello'.'china') //hello china
log('hello'.' ')//hello world
Copy the code

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'.' ') // Hello
Copy the code

The way ES6 is written has two additional benefits. First, the reader of the code can immediately recognize which parameters can be omitted without having to look at the function body or documentation. Secondly, it is beneficial for future code optimization. Even if the future version removes this parameter completely in the external interface, it will not cause the previous code to fail to run.

The default expression can be a function

function getVal(val) {
    return val + 5;
}
function add2(a, b = getVal(5)) {
    return a + b;
}
console.log(add2(10));
Copy the code

Little practice

What is the difference between the following two ways of writing?

/ / write one
function m1({x = 0, y = 0} = {}) {
  return [x, y];
}

/ / write two
function m2({x, y} = { x: 0, y: 0 }) {
  return [x, y];
}
Copy the code

Both methods set default values for function parameters. The difference is that the default values of function parameters are empty objects, but the default values of object deconstruction assignment are set. The default value of the two function arguments is an object with specific properties, but the default value of the object’s destruct assignment is not set.

// The function has no arguments
m1() / / [0, 0]
m2() / / [0, 0]

// both x and y have values
m1({x: 3.y: 8}) / / [3, 8]
m2({x: 3.y: 8}) / / [3, 8]

// if x has a value and y has no value
m1({x: 3}) / / [3, 0]
m2({x: 3}) // [3, undefined]

// if x and y have no values
m1({}) / / (0, 0),
m2({}) // [undefined, undefined]

m1({z: 3}) / / [0, 0]
m2({z: 3}) // [undefined, undefined]
Copy the code

Rest parameters

ES6 introduces the REST parameter (of the form… Variable name), used to get extra arguments to a function so you don’t need to use the arguments object. The rest argument goes with a variable that puts the extra arguments into an array.

function add(. values) {
 
  let sum = 0;

  for (var val of values) {
    sum += val;
  }

  return sum;
}

add(2.5.3) / / 10
Copy the code

The add function in the above code is a summation function that can be passed any number of arguments using the REST argument.

Arrow function ***

ES6 allows functions to be defined using arrows =>

let f = v= >v;
/ / is equivalent to
let f = function(v){
    return v;
}

// There is one argument
let add = value= > value;

// There are two arguments
let add = (value,value2) = > value + value2;

let add = (value1,value2) = >{
    
    return value1 + value2;
} 
/ / no parameters
let fn = (a)= > "hello world";

let doThing = (a)= >{}// If the arrow function returns an object directly, parentheses must be placed around the object, otherwise an error will be reported.
let getId = id= > ({id: id,name: 'mjj'}) / / note
let obj = getId(1);
Copy the code

What the arrow function does

  • Make the expression more concise

    const isEven = n= > n % 2= =0;
    const square = n= > n * n;
    Copy the code
  • Simplify the callback function

    // The normal function
    [1.2.3].map(function (x) {
      return x * x;
    });
    
    // arrow function
    [1.2.3].map(x= > x * x);
    Copy the code

Use caution points

  • No this binding

    let PageHandler = {
        id:123.init:function(){
            document.addEventListener('click'.function(event) {
                this.doSomeThings(event.type);
            },false);
        },
        doSomeThings:function(type){
            console.log('Event type:${type}The current id:The ${this.id}`);
        }
    }
    PageHandler.init();
    
    // Solve this pointing problem
    let PageHandler = {
        id: 123.init: function () {
            // Use bind to change the direction of the internal function this
            document.addEventListener('click'.function (event) {
                this.doSomeThings(event.type);
            }.bind(this), false);
        },
        doSomeThings: function (type) {
            console.log('Event type:${type}The current id:The ${this.id}`);
        }
    }
    PageHandler.init();
    
    let PageHandler = {
        id: 123.init: function () {
            // The arrow function has no reference to this. The value of this inside the arrow function can only be determined by looking up the scope chain
    
            // If the arrow function is included by a non-arrow function, the value of this is equal to the function's object, otherwise it is the global window object
            document.addEventListener('click', (event) => {
                console.log(this);
                this.doSomeThings(event.type);
            }, false);
        },
        doSomeThings: function (type) {
            console.log('Event type:${type}The current id:The ${this.id}`);
        }
    }
    PageHandler.init();
    Copy the code
  • There are no Arguments objects in the arrow function

    var getVal = (a,b) = > {
        console.log(arguments);
        return a + b;
    }
    console.log(getVal(1.2)); //arguments is not defined
    Copy the code
  • Arrow functions cannot instantiate objects using the new keyword

    let Person = (a)= >{}
    let p1 = new Person();// Person is not a constructor
    Copy the code

Object extension

A concise representation of the property

const name = 'Joe';
const age = 19;
const person = {
    name, // Equivalent to name:name
    age,
    // The method can also be abbreviated
    sayName() {
        console.log(this.name);
    }
}
person.sayName();
Copy the code

This notation is handy for the return value of a function.

function getPoint() {
  const x = 1;
  const y = 10;
  return {x, y};
}

getPoint()
// {x:1, y:10}
Copy the code

Object extension operator

const [a, ...b] = [1.2.3];
a / / 1
b / / [2, 3]
Copy the code
Deconstruction assignment

Destructible assignment of an object is used to take values from an object, which is equivalent to assigning all of the target object’s Enumerable properties that have not yet been read to the specified object. All the keys and their values are copied to the new object.

let{ x, y, ... z } = {x: 1.y: 2.a: 3.b: 4 };
x / / 1
y / / 2
z // { a: 3, b: 4 }
Copy the code

The destruct assignment must be the last argument, or an error will be reported

let { ...x, y, z } = obj; // Syntax error
let{ x, ... y, ... z } = obj;// Syntax error
Copy the code

Extended operator

Object extension operator (…) Retrieves all traversable properties of the parameter object and copies them to the current object.

let z = { a: 3.b: 4 };
letn = { ... z }; n// { a: 3, b: 4 }
Copy the code

The extension operator can be used to merge two objects.

letab = { ... a, ... b };/ / is equivalent to
let ab = Object.assign({}, a, b);
Copy the code

Promise object

Asynchronous programming module is becoming more and more important in front-end development. From the very beginning of XHR to the encapsulation of Ajax, attempts have been made to solve the problem of asynchronous programming. With the advent of the new ES6 standard, there are new solutions for handling asynchronous data flows. In traditional Ajax requests, when data between asynchronous requests was dependent on each other, inelegant layers of callbacks, commonly known as “callback hell,” could be a bit daunting. Promise was the way to move away from callback hell and write more elegant asynchronous code.

The downside of callback hell is the following:

  • Code bloat.
  • Poor readability.
  • The coupling degree is too high and the maintainability is poor.
  • Poor code reuse.
  • Bug prone.
  • Exceptions can only be handled in callbacks.

In practice, it turns out that promises aren’t perfect. Async/Await is one of the most revolutionary features added to JavaScript in recent years. Async/Await provides an alternative way to make asynchronous code look like synchronous code. Let’s take a look at these two options for handling asynchronous programming.

What is a Promise

Promise is a solution to asynchronous programming:

Syntactically, a Promise is an object that fetches messages for asynchronous operations;

In its original sense, it is a promise that will give you results over time.

This is a big pity. There are three states of promise: pending, successful, and rejected.

Once the state has changed, it will never change.

Once a Promise instance is created, it executes immediately.

Look at some familiar code:

// Promise is a constructor that has all, Reject,resolve,race methods on its own and then, catch, and so on on its prototype
let p = new Promise((resolve,reject) = >{
	// Do some asynchronous operations
	setTimeout((a)= >{
	/* let res = {ok:1, data:{name:" "}} */
		let res = {
			ok:0.error:new Error('wrong')}if(res.ok === 1){
			resolve(res.data);
		}else{
			reject(res.error.message)
		}

	}, 1000)})Copy the code

The state and value of the Promise

Promise objects can be in three states

  • Pending
  • This is a big pity.
  • Rejected(failed)

The state can only change from Pending to depressing or from Pending to Rejected. After the state changes, it will not change again and will always remain in this state.

The Promise value is the value passed to the callback function when the state changes

The arguments in the above example, resolve and reject, are functions that change the state of a Promise and the value of the incoming Promise

Resolve and reject

  • resolve: Changes the state of the Promise object fromPendingintoThis is a big pity.
  • reject: Changes the state of the Promise object fromPendingintoRejected(failed)
  • resolverejectCan be passed a value of any type as an argumentPromiseObject successfully(Fulfilled)And failure(Rejected)The value of the

Then method

p.then((data) = >{
	console.log(data);
    return data;
},(error)=>{
	console.log(error)
}).then(data= >{
    console.log(data);
})
Copy the code

The promise’s then method returns a Promise object, so the chain call can continue

We can continue to modify the above code, because the above code does not pass parameters

function timeout(ms) {
    return new Promise((resolve, reject) = > {
        setTimeout((a)= > {
            resolve('hello world')
        }, ms);
    })
}
timeout(1000).then((value) = > {
    console.log(value);
})
Copy the code

Rules for the THEN method

  • thenThe next input to the method requires the last output
  • If another promise is returned after a promise is executed, the execution result of the promise is passed to the next timethenIn the
  • ifthenReturns a normal value instead of a Promise object, which will be the result of the success of the next THEN
  • If the currentthenIf you fail, you go nextthenThe failure of the
  • If undefined is returned, success or failure will be followed by the next success
  • Catch is when an error is not handled
  • thenIf the method is not written to, the value is passed through to the next onethenIn the

Promise encapsulates XHR objects

const getJSON = function (url) {
    return new Promise((resolve, reject) = > {
        const xhr = new XMLHttpRequest();
        xhr.open('GET', url);
        xhr.onreadystatechange = handler;
        xhr.responseType = 'json';
        xhr.setRequestHeader('Accept'.'application/json');
        xhr.send();
        function handler() {
            console.log(this.readyState);
            if (this.readyState ! = =4) {
                return;
            }
            if (this.status === 200) {
                resolve(this.response);
            } else {
                reject(new Error(this.statusText));
            }
        }
    })
}
getJSON('https://free-api.heweather.net/s6/weather/now?location=beijing&key=4693ff5ea653469f8bb0c29638035976')
    .then((res) = > {
    console.log(res);

}, function (error) {
    console.error(error);

})

// Chain calls to the then method
getJSON('https://free-api.heweather.net/s6/weather/now?location=beijing&key=4693ff5ea653469f8bb0c29638035976')
    .then((res) = >{
    return res.HeWeather6;
}).then((HeWeather6) = >{
    console.log(HeWeather6);
})
Copy the code

Catch method

Catch (err=>{}) is equivalent to then(null,err=>{})

getJSON('https://free-api.heweather.net/s6/weather/now?location=beijing&key=4693ff5ea653469f8bb0c29638035976')
    .then((json) = > {
    console.log(json);
}).then(null,err=>{
    console.log(err);   
})
/ / equivalent to the
getJSON('https://free-api.heweather.net/s6/weather/now?location=beijing&key=4693ff5ea653469f8bb0c29638035976')
    .then((json) = > {
    console.log(json);
}).catch(err= >{
    console.log(err);   
})
Copy the code

resove()

The resolve() method will convert the existing object into a Promise object, and the state of this instance is fulfilled

let p = Promise.resolve('foo');
New Promise(resolve=>resolve('foo'));
p.then((val) = >{
    console.log(val);
})
Copy the code

reject()

The Reject () method returns a new Promise instance with the status Rejected

let p2 = Promise.reject(new Error('Wrong'));
// let p2 = new Promise((resolve,reject)=>reject(new Error(' Error ')));
p2.catch(err= > {
    console.log(err);
})
Copy the code

All () method

The all() method provides the ability to execute asynchronous operations in parallel and not execute callbacks until all asynchronous operations are complete

Imagine a page chat system where we need to obtain the user’s personal information and friend list from two different urls. These two tasks can be performed in parallel, using promise.all as shown below

let meInfoPro = new Promise( (resolve, reject) = > {
    setTimeout(resolve, 500.'P1');
});
let youInfoPro = new Promise( (resolve, reject) = > {
    setTimeout(resolve, 600.'P2');
});
// execute p1 and p2 at the same time, and execute then after they are both complete:
Promise.all([meInfoPro, youInfoPro]).then( (results) = > {
    console.log(results); // Get an Array: ['P1', 'P2']
});
Copy the code

Race () method

Sometimes, multiple asynchronous tasks are fault tolerant. For example, reading a user’s personal information from two urls at the same time only needs to get the result returned first. In this case, use promise.race () to implement:

let meInfoPro1 = new Promise( (resolve, reject) = > {
    setTimeout(resolve, 500.'P1');
});
let meInfoPro2 = new Promise( (resolve, reject) = > {
    setTimeout(resolve, 600.'P2');
});
Promise.race([meInfoPro1, meInfoPro2]).then((result) = > {
    console.log(result); // P1
});
Copy the code

Promise.all accepts an array of Promise objects, and after all completion, success will be executed uniformly;

Promise.race accepts an array of Promise objects, and as long as one completes, success is executed

For a more concrete example, deepen your understanding of the race() method

When we request an image resource, it will take too long to give feedback to the user

Use RACE to set a timeout for an asynchronous request and perform the corresponding operation after the timeout

function requestImg(imgSrc) {
   return new Promise((resolve, reject) = > {
        var img = new Image();
        img.onload = function () {
            resolve(img);
        }
        img.src = imgSrc;
    });
}
// The delay function is used to time the request
function timeout() {
    return new Promise((resolve, reject) = > {
        setTimeout((a)= > {
            reject('Image request timed out');
        }, 5000);
    });
}
Promise.race([requestImg('images/2.png'), timeout()]).then((data) = > {
    console.log(data);
}).catch((err) = > {
    console.log(err);
}); 
Copy the code

Async function

Asynchronous operations are the bane of JavaScript programming, and many people think async functions are the solution to asynchronous programming

To introduce the Async/await

  • Async /await is a new way to write asynchronous code, superior to callback functions and promises.
  • Async /await is implemented based on promises and cannot be used for normal callback functions.
  • Async /await, like Promise, is non-blocking.
  • Async /await makes asynchronous code look like synchronous code with no callback functions anymore. However, it does not change the single threaded, asynchronous nature of JS. (Asynchronous code synchronization)

Rules for using Async/await

  • Any function that starts with async will automatically return a Promise object after execution

    async function test() {}let result = test()
    console.log(result)  // Even though the test function returns nothing, we still made a Promise object
    Copy the code
  • Await must be used in async functions and cannot be used alone

    async test() {
        let result = await Promise.resolve('success')
        console.log(result)
    }
    test()
    Copy the code
  • ‘await’ needs to be followed by a Promise object, otherwise it makes no sense. And a Promise object after ‘await’ need not write ‘then’ because one of the purposes of ‘await’ is to get the parameters passed by the success state of the following Promise object.

    function fn() {
        return new Promise((resolve, reject) = > {
            setTimeout((a)= > {
                resolve('success')})})}async test() {
        let result = await fn() // Fn returns a Promise object
        console.log(result)    // Type 'success' when the Promise succeeds
    }
    
    test()
    Copy the code

The use of the Async/Await

  • To use await, functions must be identified with async
  • Await is followed by an instance of a Promise
function loadImg(src) {
    const promise = new Promise(function (resolve, reject) {
        const img = document.createElement('img')
        img.onload = function () {
            resolve(img)
        }
        img.onerror = function () {
            reject('Image load failed')
        }
        img.src = src
    })
    return promise
}
const src1 = 'https://hcdn1.luffycity.com/static/frontend/index/banner@2x_1574647618.8112254.png'
const src2 = 'https://hcdn2.luffycity.com/media/frontend/index/%E7%94%BB%E6%9D%BF.png'
const load = async function () {
    const result1 = await loadImg(src1)
    console.log(result1)
    const result2 = await loadImg(src2)
    console.log(result2)
}
load()
Copy the code

When a function executes, it will return as soon as it encounters await, wait until the triggered asynchronous operation is complete, and then execute the following statement in the function body.

Error handling of async/await

As for error handling, as mentioned in Rule 3, await can directly obtain the parameters passed by the subsequent Promise success state, but cannot capture the failure state. Here we solve this problem by adding then/catch methods to the async function wrapped with await, because according to rule 1 async itself returns a Promise object.

const load = async function () {
    try{
        const result1 = await loadImg(src1)
        console.log(result1)
        const result2 = await loadImg(src2)
        console.log(result2)
    }catch(err){
        console.log(err);
    }
}
load()
Copy the code

Why Async/Await is better?

Async/Await has many advantages over Promise, three of which are described below:

  • concise

    Using Async/Await clearly saves a lot of code. We don’t need to write.then, we don’t need to write anonymous functions to handle the resolve value of a Promise, we don’t need to define redundant data variables, and we avoid nested code.

  • The median

In front-end programming, we occasionally run into a situation where we need to send multiple requests, and later requests always rely on the data returned by the previous request. We can solve this problem either with a chained call of Promise or with async/await, however the latter is more concise

const makeRequest = (a)= > {
  return promise1()
    .then(value1= > {
      return promise2(value1)
        .then(value2= > {        
          return promise3(value1, value2)
        })
    })
}
Copy the code

With async/await, the code becomes surprisingly simple and intuitive

const makeRequest = async() = > {const value1 = await promise1()
  const value2 = await promise2(value1)
  return promise3(value1, value2)
}
Copy the code
  • Improve readability

In the following example, you need to retrieve the data and then, based on the returned data, decide whether to return directly or continue to retrieve more data.

const makeRequest = (a)= > {
  return getJSON()
    .then(data= > {
      if (data.needsAnotherRequest) {
        return makeAnotherRequest(data)
          .then(moreData= > {
            console.log(moreData)
            return moreData
          })
      } else {
        console.log(data)
        return data
      }
    })
}
Copy the code

The code nesting (6 layers) is less readable and communicates only the need to pass the final result to the outermost Promise. Writing with async/await greatly improves readability:

const makeRequest = async() = > {const data = await getJSON()
  if (data.needsAnotherRequest) {
    const moreData = await makeAnotherRequest(data);
    console.log(moreData)
    return moreData
  } else {
    console.log(data)
    return data    
  }
}
Copy the code

Basic usage of Class

Introduction to the

The traditional way to generate instance objects in the JavaScript language is through constructors

function Person(name,age) {
    this.name = name;
    this.age = age;
}
Person.prototype.sayName  = function() {
    return this.sayName;
}
let p = new Person('Little Pony'.18);
console.log(p);
Copy the code

This is very different from traditional object-oriented languages such as C++ and Java, and can easily confuse new programmers

ES6 provides a more traditional language approach, introducing the concept of classes as templates for objects. With the class keyword, you can define a class.

Basically, ES6 classes can be seen as a syntactic candy that does most of what ES5 does. The new class writing method simply makes object prototype writing clearer and more like object-oriented programming syntax. The above code is rewritten using ES6 class, as follows

class Person {
    // The constructor method is the default method of a class, which is automatically called when an object instance is generated using the new command. A class must have a constructor method, which is added by default if not defined
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    Prototype = function sayName(){}
    sayName(){
        return this.name; }}console.log(Person===Person.prototype.constructor)
Copy the code

Class methods that contain this inside point to instances of the class by default

The Module of modularity

An overview of the

Historically, JavaScript has not had a module system that allows you to break up a large program into small interdependent files and put them together in a simple way. Other languages have this functionality, such as Ruby’s require, Python’s import, and even CSS has @import, but JavaScript has no support for any of this, which is a huge barrier to developing large, complex projects.

Prior to ES6, there were several module loading schemes developed by the community, the most important being CommonJS and AMD. The former is used for servers and the latter for browsers. ES6 in the language standard level, the realization of module function, and the implementation is quite simple, can completely replace CommonJS and AMD specifications, become a common browser and server module solution.

The ES6 module is designed to be as static as possible, so that the module dependencies, as well as the input and output variables, can be determined at compile time. Both CommonJS and AMD modules can only determine these things at runtime. For example, a CommonJS module is an object, and you have to look for object properties when you enter it.

The export command

The function of the module consists of two commands: export and import. The export command is used to specify the external interface of a module, and the import command is used to input functions provided by other modules.

A module is an independent file. All variables inside the file are not available externally. If you want outsiders to be able to read a variable inside a module, you must use the export keyword to output that variable

//module/index.js
export const name = 'zhangsan ';
export const age = 18;
export const color = 'red ';
export const sayName = function() {
    console.log(fristName);
}

// You can do that
const name = 'zhangsan ';
const age = 18;
const color = 'red ';
const sayName = function() {
    console.log(fristName);
}
export {name,age,color,sayName}

Copy the code

The import command

After the module’s external interface is defined using the export command, other JS files can load the module using the import command.

//main.js
import {name,age,color,sayName,fn} from './modules/index.js';
Copy the code

If you want to rename the input variable, the import command uses the as keyword to rename the input variable

import * as obj from './modules/index.js';
console.log(obj);
Copy the code

Export the default command

Use the export default command to specify the default output for the module

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

// or write it as
function foo() {
  console.log('foo');
}

export default foo;
Copy the code

The import command can specify any name for the anonymous function when the module is loaded by other modules

//import-default.js
import customName from './export-default.js'
customNmae();//foo
Copy the code

If you wanted to enter default methods and other interfaces in an import statement, you could write it like this

import customName,{add} from 'export-default.js'
Copy the code

The corresponding export statement is as follows

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

export function add(){
    console.log('add')}Copy the code

Export default can also be used to output classes.

// MyClass.js
export default class Person{... }// main.js
import Person from 'MyClass';
let o = new Person();
Copy the code