First of all, I wish you a happy National Day, to experience the happiness of life, but also wish the motherland a happy birthday, more and more powerful, more and more prosperous.

The body of the

1. Let and const

let

This is similar to var, except that the variables declared by let are valid only within the block in which the let command resides.

Features:

  • There is no variable promotion
  • Temporary dead zones — As long as a let command exists in the block-level scope, variables declared by it are “bound” to the region and are no longer subject to external influence
  • Repeated declarations are not allowed
  • Block-level scope — enveloped by {}, the outside cannot access the inside

Application Case and Analysis:

/ / using var
for (var i = 0; i < 5; i++) {
  setTimeout(function () {
    console.log(i);
  });
}   // => 5

/ / use the let
for (let i = 0; i < 5; i++) {
  setTimeout(function () {
    console.log(i);
  });
}   // => 0
Copy the code

In the let code above, the variable I is declared by the let. The current I is only valid for this round, so each time I is actually a new variable. The JavaScript engine internally will remember the value of the last round of the loop, and when I is initialized for this round, I’m just going to do it on the basis of what I did in the last cycle so I’m going to print out I normally.

Note:

  1. Another special feature of the for loop is that the part that sets the loop variables is a parent scope, and the body of the loop is a separate child scope, so we can access the value of I from within the body of the loop.
  2. When let and var are globally declared, var can be accessed through the property of window but let cannot.

const

Const declares a read-only constant. Once declared, the value of the constant cannot be changed. Const essentially guarantees that the data stored at the memory address to which the variable points cannot be changed. For data of simple types (numbers, strings, Booleans), the value is stored at the memory address that the variable points to and is therefore equivalent to a constant. For complex data (mainly objects and arrays), the memory address to which a variable points holds only a pointer to the actual data. Const only guarantees that the pointer is fixed, and that the data structure to which it points is mutable. Therefore, you must be very careful when declaring an object as a constant.

Therefore, when we use const, we must not declare the value without initializing it, otherwise we will report an error:

const a;
// SyntaxError: Missing initializer in const declaration
Copy the code

Other features of const are similar to those of let. It is generally recommended to declare constants with uppercase names.

2. Numerical extension

ES6 provides two new methods, number.isfinite () and number.isnan (), on the Number object.

Number.isFinite()

Number.isfinite () is used to check if a Number isFinite, i.e. not Infinity. Note that number. isFinite always returns false if the parameter type is not numeric.

Number.isFinite(0.8); // true
Number.isFinite(NaN); // false
Number.isFinite(Infinity); // false
Number.isFinite('hello');  // false
Number.isFinite(true);  // false
Copy the code

Number.isNaN()

Check whether a value isNaN. If the parameter type is not NaN, number. isNaN returns false

IsNaN and number.isfinite differ from the traditional global methods isFinite() and isNaN() in that the traditional methods call Number() to convert a non-numeric value into a numeric value before judging it. The new methods only work with numeric values. Number.isfinite () will always return false for non-values, number.isnan () will only return true for nans, and will always return false for non-Nans.

isFinite(11) // true
isFinite("11") // true
Number.isFinite(11) // true
Number.isFinite("11") // false

isNaN(NaN) // true
isNaN("NaN") // true
Number.isNaN(NaN) // true
Number.isNaN("NaN") // false
Number.isNaN(10) // false
Copy the code

Number.parseInt(), Number.parseFloat()

ES6 ports the global methods parseInt() and parseFloat() to the Number object, leaving the behavior completely unchanged. The goal is to gradually reduce the global methods and make the language more modular

Number.isInteger()

Number.isinteger () is used to determine whether a value is an integer; Inside JavaScript, integers and floats are stored the same way, so 25 and 25.0 are treated as the same value; If the argument is not a value, number. isInteger returns false; Since JavaScript values are stored in 64-bit double precision format, the value can be accurate up to 53 binary bits. If the value is more accurate than this, the 54th and subsequent bits will be discarded. In this case, number.isINTEGER may misjudge.

Number.isInteger(15) // true
Number.isInteger(15.1) // false
Number.isInteger(15.0) // true
Number.isInteger('10') // false
Number.isInteger(true) // false
// Error will be misjudged
Number.isInteger(5.0000000000000002) // true
Copy the code

Math.trunc()

The math. trunc method is used to remove the fractional part of a number and return the integer part; For non-numeric values, Math.trunc internally converts them to numeric values first using the Number method; Returns NaN for null values and values that cannot intercept integers

Math.trunc(2.1) / / 2
Math.trunc(2.9) / / - 2
Math.trunc(0.1254) / / - 0
Math.trunc('125.456') / / 125
Math.trunc(true) / / 1
Math.trunc(false) / / 0
Math.trunc(null) / / 0
Math.trunc(NaN);      // NaN
Math.trunc('bar');    // NaN
Math.trunc();         // NaN
Math.trunc(undefined) // NaN
Copy the code

Math.cbrt()

The Math. CBRT method is used to calculate the cube root of a number. For non-numeric values, the math.cbrt method internally also uses the Number method to convert them to numeric values first

Math.cbrt(- 1) // -1
Math.cbrt(0)  / / 0
Math.cbrt(8)  / / 2
Math.cbrt('8') / / 2
Math.cbrt('hello') // NaN
Copy the code

Math.hypot()

The math.hypot method returns the square root of the sum of squares of all parameters

Math.hypot(3.4);        / / 5
Math.hypot(3.4.5);     / / 7.0710678118654755
Math.hypot();            / / 0
Math.hypot(NaN);         // NaN
Math.hypot(3.4.'foo'); // NaN
Math.hypot(3.4.'5');   / / 7.0710678118654755
Math.hypot(- 3); 
Copy the code

Now, with this API, isn’t it convenient to do an n-dimensional Pythagorean theorem?

Exponential operator

ES2016 has added an exponent operator (**). One characteristic of this operator is the right combination, rather than the usual left combination. When multiple exponential operators are used together, they are computed from the far right.

// equivalent to 2 ** (3 ** 2)
2支那3支那2  / / 512
/ / = > math.h pow (2, and Math. The pow (3, 2))
Copy the code

Es6 + also extends more numerical apis that you can study on your own.

3. Array extensions

Extension operator

The spread operator is three points (…) Turns an array into a comma-separated sequence of arguments

Application:

  1. Copy the array
const a1 = [1.2];
const a2 = [...a1];
Copy the code
  1. Merge array
const arr1 = ['1'.'2'];
const arr2 = ['c', {a:1}];// ES6's merge array
[...arr1, ...arr2]
Copy the code

Note: Both of these methods are shallow copies, so be careful when using them.

  1. Convert a string to an array

Four-byte Unicode characters can be correctly recognized using the extension operator. Any function that involves manipulating a four-byte Unicode character has this problem. Therefore, it is best to rewrite everything with the extension operator.

[...'xuxi']
// [ "x", "u", "x", "i" ]
Copy the code
  1. An object that implements the Iterator interface
let nodeList = document.querySelectorAll('div');
let arr = [...nodeList];
Copy the code

In the above code, the querySelectorAll method returns a NodeList object. It’s not an array, it’s an array-like object. The extension operator can turn it into a true array because NodeList objects implement iterators.

Array.from()

The array. from method is used to turn class objects into true arrays: array-like objects and traversable objects (including the new ES6 data structures Set and Map).

In practice, we use array. from for the NodeList collection returned by DOM operations and the arguments object inside the function.

/ / the NodeList object
let nodeList = document.querySelectorAll('p')
let arr = Array.from(nodeList)

/ / the arguments object
function say() {
  let args = Array.from(arguments);
}
Copy the code

Array.from can also take a second argument, which acts like an Array’s map method, to process each element and put the processed value into the returned Array.

Array.from([1.2.4], (x) => x + 1)
/ / [2, 3, 5]
Copy the code

Array.of()

The array. of method is used to convert a set of values into an Array. Array.of can basically be used in place of Array() or new Array(), and there is no overloading due to different arguments. It’s very uniform in its behavior.

Array.of() / / []
Array.of(undefined) // [undefined]
Array.of(2) / / [2]
Array.of(21.2) / / [21, 2]
Copy the code

Array instance copyWithin()

The array instance’s copyWithin() method copies the member at the specified location to another location (overwriting the original member) within the current array, and then returns the current array. In other words, when you use this method, you’re modifying the current array.

It takes three arguments:

  • Target (required) : Replace data from this location. If it’s negative, it’s reciprocal.
  • Start (Optional) : Data is read from this position. The default value is 0. If the value is negative, the calculation starts from the end.
  • End (optional) : Stop reading data at this position, which is equal to the array length by default. If the value is negative, the calculation starts from the end.
[11.21.31.41.51].copyWithin(0.3)  // => [41, 51, 31, 41, 51]
// Copy bit 3 to bit 0
[1.2.3.4.5].copyWithin(0.3.4)
Copy the code

Find () and findIndex() for array instances

The find method of an array instance is used to find the first member of the array that meets the criteria. Its argument is a callback function that is executed for all array members until it finds the first member that returns true, and then returns that member. If there are no eligible members, undefined is returned. The findIndex method for an array instance works much like the find method, returning the location of the first member of the array that meets the criteria, or -1 if none of the members meet the criteria. Both methods can take a second argument, which binds to the this object of the callback function.

// find
[1.5.8.12].find(function(value, index, arr) {
  return value > 9;
}) / / 12

// findIndex
[1.5.5.15].findIndex(function(value, index, arr) {
  return value > 9;
}) / / 3

// The second argument
function f(v){
  return v > this.age;
}
let person = {name: 'John'.age: 20};
[10.12.26.15].find(f, person);    / / 26
Copy the code

Fill () for array instances

The fill method fills an array with the given value. The fill method can also take a second and third argument that specifies where the fill starts and ends. Note that if the populated object is of type object, then the object is assigned to the same memory address, not the deep-copy object.

new Array(3).fill(7)
/ / (7, 7, 7)

['a'.'b'.'c'].fill(7.1.2)
// ['a', 7, 'c']

// Fill in the reference type
let arr = new Array(2).fill({name: "xuxi"});
arr[0].name = "xu";
arr
// [{name: "xu"}, {name: "xu"}]

let arr = new Array(2).fill([]);
arr[0].push(1);
arr
/ / [[1], [1]]
Copy the code

Array instance includes()

The array.prototype. includes method returns a Boolean value indicating whether an Array contains the given value. The second argument to the method represents the starting position of the search, which defaults to 0. If the second argument is negative, it indicates the reciprocal position, and if it is greater than the array length (for example, if the second argument is -4, but the array length is 3), it resets to start at 0.

[1.4.3].includes(3)     // true
[1.2.4].includes(3)     // false
[1.5.NaN.6].includes(NaN) // true
Copy the code

Flat (), flatMap() for array instances

Flat () is used to “flattens” a nested array into a one-dimensional array. This method returns a new array with no effect on the original data. Flat () will only “flatten” one layer by default. If you want to “flatten” multiple layers of nested arrays, you can write the flat() method argument as an integer representing the number of layers you want to flatten. The default is 1. If you want to convert to a one-dimensional array regardless of the number of nesting levels, you can use the Infinity keyword as an argument. The flatMap() method executes a function on each member of the original array, and then executes the flat() method on the array of returned values. This method returns a new array without changing the original array. FlatMap () can only expand one level of an array. The flatMap() method can also take a second argument to bind this in the traversal function.

[1.2[3[4.5]]].flat()
// [1, 2, 3, [4, 5]]

[1.2[3[4.5]]].flat(2)
// [1, 2, 3, 4, 5]

[1[2[3]]].flat(Infinity)
/ / [1, 2, 3]

// If the array is empty, the flat() method skips the empty space
[1.2.4.5].flat()
// [1, 2, 4, 5]

// flatMap
[2.3.4].flatMap((x) = > [x, x * 2])
// [2, 4, 3, 6, 4, 8]
Copy the code

4. Extension of functions

Default values for function arguments

function say(name = 'xuxi') {
    alert(name)
}
Copy the code

Note:

  • Parameter variables are declared by default, so they cannot be declared again with let or const
  • When using parameter defaults, the function cannot have parameters with the same name
  • The parameter default value is not passed, but the default value expression is recalculated each time. That is, parameter defaults are lazily evaluated
  • If the parameter is passed in, undefined will trigger the parameter to be equal to the default value, null does not. The key point

The length attribute of the function

When the default value is specified, the length property of the function returns the number of arguments without a default value. That is, if you specify a default value, the length property will be distorted; If the default value is set for an argument that is not a trailing argument, then the length property is no longer included in the following arguments.

(function (a) {}).length / / 1
(function (a = 5) {}).length / / 0
(function (a, b, c = 5) {}).length / / 2
// The parameter is not a tail parameter
(function (a = 0, b, c) {}).length / / 0
(function (a, b = 1, c) {}).length / / 1
Copy the code

scope

Once the default value of the parameter is set, the parameter forms a separate scope when the function is declared and initialized. Once the initialization is complete, the scope will disappear. This will not occur if the parameter default value is not set.

Arrow function

Since the arrow function is relatively simple to use, let’s take a look at the following points:

  • The this object in the body of the function is the object that was defined, not the object that was used.

  • It cannot be used as a constructor, that is, it cannot use the new command, otherwise an error will be thrown.

  • Do not use the Arguments object. It does not exist in the function body. If so, use the REST parameter instead.

  • You cannot use the yield command, so arrow functions cannot be used as Generator functions.

Not suitable for:

// Define a method for an object that includes this,
// Since objects do not constitute a separate scope, the scope in which the say arrow function is defined is global
const person = {
  year: 9.say: (a)= > {
    this.year--
  }
}

// When dynamic this is required, the arrow function should not be used
// When the code is running, clicking the button will cause an error, because the listener function of the button is an arrow function, so this inside is a global object
var btn = document.getElementById('btn');
btn.addEventListener('click', () = > {this.classList.add('on');
});
Copy the code

5. Object extensions

Object extension operator

Object extension operator (…) Copy all the traversable properties of the parameter object to the current object. Equivalent to using the object.assign () method

let a = {w: 'xu'.y: 'xi'}
let b = {name: '12'}
letab = { ... a, ... b };/ / is equivalent to
let ab = Object.assign({}, a, b);
Copy the code

Object.is()

It is used to compare whether two values are strictly equal, which is basically the same as the strict comparison operator (===). The only difference is that +0 is not equal to -0, and NaN is equal to itself.

+0= = =0 //true
NaN= = =NaN // false

Object.is(+0.0) // false
Object.is(NaN.NaN) // true
Copy the code

Object.assign()

For object merge, copy all enumerable properties of the source object to the target object; If there is only one argument, object. assign returns that argument directly; Since undefined and NULL cannot be converted to objects, an error will be reported if they are used as arguments. Other types of values (that is, numbers, strings, and Booleans) are not the first argument, and no error is reported. However, except that the string is copied into the target object as an array, none of the values have any effect.

// Merge objects
const target = { a: 1.b: 1 };

const source1 = { b: 2.c: 2 };
const source2 = { c: 3 };

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

// Non-object and string types are ignored
const a1 = '123';
const a2 = true;
const a3 = 10;

const obj = Object.assign({}, a1, a2, a3);
console.log(obj); // {"0": "1", "1": "2", "2": "3"}
Copy the code

Note:

  • The object. assign method implements a shallow copy, not a deep copy. That is, if the value of a property in the source object is an object, then the target object copies a reference to that object
  • For nested objects that encounter attributes of the same name, object. assign is handled by replacing, not adding
  • Object.assign can be used to handle arrays, but treats arrays as objects
Object.assign([1.2.3], [4.5])
/ / [4, 5, 3]
Copy the code
  • Object.assign can only copy values. If the value to be copied is a value function, the value is evaluated and then copied
const a = {
  get num() { return 1}};const target = {};

Object.assign(target, a)
// { num: 1 }
Copy the code

Application scenario:

  • Add properties and methods to an object
  • Clone/merge objects
  • Specify a default value for the property

Object.keys()

Returns an array of keys for all traversable properties of the argument object itself (not inherited)

Object.values()

Returns an array of keys for all traversable properties of the argument object itself (not inherited). Note: Return the order of the members of the array: if the property is named number, it is traversed from the smallest to the largest

const obj = { 100: '1'.2: '2'.7: '3' };
Object.values(obj)
/ / / "2", "3", "1"]
Copy the code

Object.entries()

Returns an array of key-value pairs for all traversable properties of the argument object itself (not inherited); If the property name of the original object is a Symbol value, the property is ignored

const obj = { a: '1'.b: 1[Symbol()] :123 };
Object.entries(obj)
// [ ["a", "1"], ["b", 1] ]
Copy the code

Object.fromEntries()

The object.fromentries () method is the reverse of object.entries () and is used to convert an array of key-value pairs into an Object

Object.fromEntries([
  ['a'.'1'],
  ['b'.2]])// { a: "1", b: 2 }
Copy the code

Application scenario:

  • Restores the data structure of the key-value pair to an object, and is therefore particularly suitable for converting Map structures to objects
  • With the URLSearchParams object, turn the query string into an object
Object.fromEntries(new URLSearchParams('name=xuxi&year=24'))
// { name: "xuxi", year: "24" }
Copy the code

6. symbol

ES6 introduces a new primitive data type, Symbol, which represents unique values. It is the seventh data type in the JavaScript language. The first six are undefined, NULL, Boolean, String, Number, and Object. The Symbol value is generated by the Symbol function. Attribute names that are of type Symbol are unique and are guaranteed not to conflict with other attribute names.

Note:

  • Do not use the new command before the Symbol function, otherwise an error will be reported
  • Because the Symbol value is not an object, attributes cannot be added. Essentially, it is a data type similar to a string
  • The Symbol function takes a string as an argument that describes the Symbol instance, making it easy to distinguish
  • The parameters to the Symbol function simply represent a description of the current Symbol value, so the return values of the Symbol function with the same parameters are not equal
  • The Symbol value cannot be evaluated with a value of another type
  • The dot operator cannot be used when the Symbol value is used as an object property name
  • Inside an object, when a attribute is defined using a Symbol value, the Symbol value must be enclosed in square brackets
  • When the Symbol value is used as the property name, the property is still public, not private
  • Properties do not appear in for… In, for… Of loop, will not be the Object. The keys (), Object, getOwnPropertyNames (), JSON. The stringify () returns. However, it is not the private property, use Object. GetOwnPropertySymbols method can get all the Symbol of specified Object attribute names.

Symbol. The for (), Symbol. KeyFor ()

Symbol.for() takes a string as a parameter and searches for a Symbol value with that parameter as its name. If so, return the Symbol value, otherwise create and return a new Symbol with the string name. The Symbol. KeyFor method returns the key of a registered value of type Symbol

let a1 = Symbol.for('123');
let a2 = Symbol.for('123');

a1 === a2 // true

// Both Symbol() and Symbol() generate a new Symbol.
// The difference is that the former is registered for search in the global environment, while the latter is not
Symbol.keyFor(a1) / / "123"
let c2 = Symbol("f");
Symbol.keyFor(c2) // undefined
Copy the code

7. Set and Map data structures

set

ES6 provides a new data structure, Set, which is similar to an array, but whose member values are unique, with no duplicate values. The Set itself is a constructor that generates a Set data structure.

Instance properties and methods:

  • Add (value) : Adds a value, returning the Set structure itself.
  • Delete (value) : deletes a value and returns a Boolean value to indicate whether the deletion is successful.
  • Has (value) : Returns a Boolean value indicating whether the value is a member of a Set.
  • Clear () : clear all members, no return value.
s.add(1).add(3).add(3);
// Note that 3 is added twice

s.size / / 2

s.has(1) // true
s.has(2) // false

s.delete(3);
s.has(3) // false
Copy the code

Traversal operation:

  • Keys () : the iterator that returns the key name
  • Values () : the iterator that returns the key value
  • Entries () : iterator that returns key-value pairs
  • ForEach () : Uses a callback function to iterate over each member

The order in which a Set is traversed is the order in which it is inserted. This feature can be useful when, for example, using a Set to store a list of callback functions ensures that they are called in the order in which they were added.

Application scenario:

// Deduplicate the array
let arr = [1.2.2.3];
let unique = [...new Set(arr)];
// or
function dedupe(array) {
  return Array.from(new Set(array));
}

let a = new Set([1.2.3]);
let b = new Set([4.3.2]);

/ / and set
let union = new Set([...a, ...b]);
// Set {1, 2, 3, 4}

/ / intersection
let intersect = new Set([...a].filter(x= > b.has(x)));
// set {2, 3}

/ / difference set
let difference = new Set([...a].filter(x= >! b.has(x)));// Set {1}
Copy the code

map

Like an object, it is a collection of key-value pairs. Values of any type (including objects) can be used as keys. The Map structure provides a value-value correspondence, which is a more complete implementation of the Hash structure.

Instance properties and methods:

  • Size attribute: returns the total number of members of the Map structure
  • Set (key, value): The set method sets the corresponding key value of the key and returns the entire Map structure. If the key already has a value, the key is updated, otherwise the key is generated, and the set method returns the Map itself, so it can be chained
  • Get (key) : The get method reads the key value corresponding to the key. If the key cannot be found, undefined is returned
  • Has (key) : The has method returns a Boolean value indicating whether a key is in the Map data structure
  • Delete (key) : The delete method deletes a key, returning true. If deletion fails, return false
  • Clear () : The clear method clears all members and returns no value

The traversal method is similar to the set. The Map structure is converted into an array structure. The faster method is to use the extended operator (…) in combination with the Map structure. :

let map = new Map([[1.'one'],
  [2.'two'],
  [3.'three']]); [...map.keys()]/ / [1, 2, 3]

[...map.values()]
// ['one', 'two', 'three']

[...map.entries()]
// [[1,'one'], [2, 'two'], [3, 'three']]

[...map]
// [[1,'one'], [2, 'two'], [3, 'three']]
Copy the code

Array to map:

new Map([[true.7], [{foo: 3},'abc']]])
// Map {true => 7, Object {foo: 3} => ['abc']}
Copy the code

Convert Map to object:

function strMapToObj(strMap) {
  let obj = Object.create(null);
  for (let [k,v] of strMap) {
    obj[k] = v;
  }
  return obj;
}

let myMap = new Map().set('yes'.true).set('no'.false);
strMapToObj(myMap)
// { yes: true, no: false }
Copy the code

Converting objects to Maps

function objToStrMap(obj) {
  let strMap = new Map(a);for (let k of Object.keys(obj)) {
    strMap.set(k, obj[k]);
  }
  return strMap;
}

objToStrMap({yes: true.no: false})
// [ [ 'yes', true ], [ 'no', false ] ]
Copy the code

8. The Proxy and Reflect

For the introduction of Proxy and Reflect, I’ll write a full module on how to use them.

9. Promise

A Promise is a solution to asynchronous programming that is simply a container that holds the results of an event that ends in the future. Syntactically, a Promise is an object from which to get messages for asynchronous operations.

Features:

  • The state of an object is unaffected. A Promise object represents an asynchronous operation that can be in three states: Pending, Fulfilled, or Rejected. Only the result of an asynchronous operation can determine the current state, which cannot be changed by any other operation.
  • Once the state changes, it doesn’t change again, and it can happen any time. The whole process is irreversible.

Use:

  • Basic usage
// Load images asynchronously
function loadImageAsync(url) {
 return new Promise(function(resolve, reject) {
   var image = new Image();

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

   image.onerror = function() {
     reject(new Error('Image loading failed'));
   };

   image.src = url;
 });
}
/ / use
loadImageAsync('http://xxxx/api').then((data) = > {
   // some code
}).catch(err= > console.log(err))
Copy the code

The resolve function changes the state of the Promise object from “unfinished” to “successful” (Pending => Resolved) and passes the result of the asynchronous operation as a parameter. The reject function changes the state of the Promise object from “unfinished” to “failed” (Pending => Rejected) and passes the error reported by the asynchronous operation as an argument.

After the Promise instance is generated, you can use the THEN method to specify callbacks for the Resolved and Reject states, respectively. The first argument to the THEN method is the callback function for the Resolved state and the second (optional) argument is the callback function for the Rejected state.

The then method returns a new Promise instance (note, not the original Promise instance). So you can write chained, where the THEN method is followed by another THEN method. The catch method is an alias for.THEN (null, rejection), which specifies the callback function when an error occurs.

  • Promise.all()

The promise. all method is used to wrap multiple Promise instances into a new Promise instance. This will be fulfilled only if all the promises in promise. all become fulfilled. In this case, the return values of the internal promises are formed into an array and passed to the callback function of promise. all. All becomes rejected as long as there is a Promise inside promise. all, and the return value of the first rejected instance is passed to the p callback.

  • Promise.race()

The promise. race method also wraps multiple Promise instances into a new Promise instance. As long as one instance of promise. race changes state first, the state of promise. race changes accordingly. The return value of the first Promise instance changed is passed to the promise.race callback function.

Implement request timeout processing:

const ajaxWithTime = (url, ms) = > Promise.race([
  fetch(url),
  new Promise(function (resolve, reject) {
    setTimeout((a)= > reject(new Error('request timeout')), ms)
  })
])
ajaxWithTime('http://xxx'.5000).then(response= > console.log(response))
.catch(error= > console.log(error))
Copy the code
  • Promise.resolve()

Convert an existing object to a Promise object. If the argument is a Promise instance, promise. resolve returns the instance unchanged. If the argument is a raw value, or if it is an object that does not have the THEN method, the promise. resolve method returns a new Promise object in the Resolved state; Note that the Promise object that is resolved immediately is at the end of the current event loop, not at the beginning of the next.

setTimeout(function () {
  console.log('3');
}, 0);

Promise.resolve().then(function () {
  console.log('2');
});

console.log('1');

/ / 1
/ / 2
/ / 3
Copy the code
  • finally()

The finally method is used to specify the action that will be performed regardless of the final state of the Promise object. It takes an ordinary callback function as an argument, which must be executed anyway

10. Async function

Async functions are the syntaxsugar of Generator functions. The await command of async functions can be followed by Promise objects and values of primitive types (numeric, string, and Boolean values, but this is equivalent to synchronous operations). The async function returns a Promise object, and you can use the THEN method to specify the next operation. Further, the async function can well be thought of as multiple asynchronous operations wrapped into a Promise object, while the await command is the syntactic sugar of the internal then command.

Application case:

1. Data is returned after a specified time

function timeout(ms) {
  return new Promise((resolve) = > {
    setTimeout(resolve, ms);
  });
}

async function asyncPrint(value, ms) {
  await timeout(ms);
  console.log(value)
}

asyncPrint('xu xi'.5000);
Copy the code

Notes:

  • The result may be rejected, so it is better to put the await command in the try… Catch block
  • Async operations following multiple await commands are better off firing at the same time if no secondary relationship exists
let [a, b] = await Promise.all([a(), b()]);
Copy the code
  • Await command can only be used in async functions. If used in normal functions, it will report an error

Application scenario:

  1. Complete asynchronous operations in sequence
async function fetchInOrder(urls) {
  // Read remote requests concurrently
  const promises = urls.map(async url => {
    const res = await fetch(url);
    return res.text();
  });

  // Output in sequence
  for (const promise of promises) {
    console.log(awaitpromise); }}Copy the code

11. class

With the class keyword, you define a class. ES6’s class is just a syntactic sugar. Most of the functions of ES5 can be done, but the class writing just makes the object prototype clearer and more like the syntax of object-oriented programming. The data type of the class is function, and the class itself points to the constructor. The prototype property of the constructor survives on the “class” in ES6. All methods of a class are defined on the prototype property of the class. In addition, all methods defined inside a class are non-enumerable.

class Person {
  constructor() {// ...
  }

  toString(){
    // ...}}/ / is equivalent to

Person.prototype = {
  toString(){},
  toValue(){}
};

// Cannot be enumerated
Object.keys(Person.prototype)
/ / []
Object.getOwnPropertyNames(Person.prototype)
// ["constructor","toString"]
// Note: the toString method in ES5 is enumerable
Copy the code

The constructor method

The method is the default method of the class and is automatically called when an object instance is generated by the new command. A class must have a constructor method. If it is not explicitly defined, an empty constructor method will be added by default. The constructor method returns an instance object (this) by default, and you can specify that another object is returned

Note: The constructor of the class cannot be called without new, and will report an error. This is a major difference from normal constructors, which can be executed without new.

There is no variable promotion

This point

If a class method has this inside it, it defaults to an instance of the class. However, you must be very careful that this method, when used alone, is likely to report an error

// Solve this problem
class Say {
  constructor() {
    // Bind this to the constructor or use the arrow function
    this.sayName = this.sayName.bind(this); }}Copy the code

The Class inheritance

Classes can be inherited from each other through the extends keyword, and subclasses must call the super method in the constructor method, otherwise an error will be reported when new instances are created. This is because a subclass does not have a this object of its own. Instead, it inherits a this object from its parent class, and if it does not call the super method, the subclass will not get this object.

class Color extends Point {
  constructor(x, y, name) {
    super(x, y); Constructor (x, y) = constructor(x, y);
    this.name = name;
  }

  toString() {
    return this.name + ' ' + super.toString(); // Call toString() of the parent class}}Copy the code

Getters and setters for Class

As in ES5, you can use the get and set keywords inside a Class to set a value function and a value function on a property, blocking access to that property

class MyHTMLElement {
  constructor(element) {
    this.element = element;
  }

  get html() {
    return this.element.innerHTML;
  }

  set html(value) {
    console.log('success', value)
    this.element.innerHTML = value; }}const el = new MyHTMLElement(el);
el.html('1111')  // success 1111
Copy the code

Class

If you put the static keyword in front of a method, it means that the method will not be inherited by the instance, but will be called directly from the class. This is called a static method.

class Hi {
  static say() {
    return 'hello';
  }
}

Hi.say() // 'hello'

let hi = new Hi();
hi.say()
// TypeError: foo.classMethod is not a function
Copy the code

Decorator ()

Class of

A decorator is a function that modifies the behavior of a class. Changes to the class’s behavior occur at compile time, not at run time.

function get(target) {
  target.get = 'GET';
}

@get
class MyHttpClass {}

console.log(MyHttpClass.get) // GET

// If one argument is not enough, you can wrap another layer of functions around the decorator
function get(type) {
  return function(target) {
    target.type = type;
    // Add instance attributes
    target.prototype.isDev = true;
  }
}

@get('json')
class MyHttpClass {}
MyHttpClass.type // 'json'

let http = new MyHttpClass();
http.isDev // true
Copy the code

Modification of methods

Modifiers can modify not only classes, but also properties of classes. Modifiers can only be used on classes and methods of classes, not functions, because function promotion exists. If there are multiple decorators for the same method, it will be executed from the outside in and then from the inside out like peeling an onion.

When modifying an attribute of a class, the modifier function can take a total of three arguments. The first argument is the target object to be modified, the second argument is the name of the attribute to be modified, and the third argument is the description of the attribute.

// The @log decorator below is used to output logs
class Kinds {
  list = []
  @log
  add(name) {
    return this.list.push(name)
  }
}

function log(target, name, descriptor) {
  var oldValue = descriptor.value;
  console.log('old', oldValue);
  // ...
  return descriptor;
}

const dog = new Kinds();

dog.add('dog');

// The onion order of execution of multiple decorators
function printN(id){
    console.log('print-0', id);
    return (target, property, descriptor) = > console.log('print-1', id);
}

class A {
    @printN(1)
    @printN(2)
    say(){}
}
// print-0 1
// print-0 2
// print-1 2
// print-1 1
Copy the code

13. module

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

export

If you want a variable inside the module to be read externally, you must export the variable using the export keyword

// lib.js
// Direct export
export var name = 'xu xi';

// Give priority to the following writing, which is more clear and elegant
var year = 1958;
export {year};

// Export the function
export function multiply(x, y) {
  return x * y;
};

// Rename using the as keyword
export {
  year as y
};

// Note: the export command specifies the external interface, and must establish a one-to-one relationship with the variables inside the module
var a = 1;
// Error: 1 is a value, not an interface
export a;
// The following error is also reported
function f() {}
export f;

// In addition, the export statement outputs the interface, and its corresponding value is a dynamic binding relationship,
// That is, through this interface, you can get the real-time value inside the module
export var a = 1;
setTimeout((a)= > a = 2.1000);  // After 1 second a becomes 2
Copy the code

The export command can appear anywhere in the module, as long as it is at the top level of the module. If it is in the block-level scope, an error will be reported, as will import. This is because there is no way to do static optimization in a conditional block, which is contrary to the design of the ES6 module.

import

Once you have defined a module’s external interface using the export command, other JS files can load the module using the import command. The import command has the effect of being promoted to the head of the entire module and is executed first. Because the import command is executed during the compile phase, before the code runs. If the same import statement is executed multiple times, it will be executed only once, not multiple times

// main.js
import {other, year} from './lib';
// Rename the input variable
import { year as y } from './lib';

/ / improve
say()
import { say } from './lib';

// Load the module as a whole
import * as lib from './lib';
console.log(lib.year, lib.say())
Copy the code

Export the default command

Specify the default output for the module

// a.js
export default function () {
  console.log('xu xi');
}

// b.js
import a from './a'
Copy the code

The last

Since more than 90% of the business can be solved with the above es6 new features, we will continue to optimize and improve in the later stage, and develop a practical project completely completed with ES6. More front issues in the public number “interesting talk front” join us to discuss it!

More recommended

  • Implementing a CMS full stack project from 0 to 1 based on nodeJS (Part 1)
  • Implementing a CMS full stack project from 0 to 1 based on nodeJS (middle)
  • Implement a CMS full stack project from 0 to 1 based on nodeJS (Part 2)
  • Implement server startup details for a CMS full stack project from 0 to 1 based on nodeJS
  • “Javascript advanced programming” core knowledge summary
  • With CSS3 to achieve stunning interviewers background that background animation (advanced source)
  • Remember an old project with cross-page communication issues and front-end implementation of file downloads
  • Write a mock data server using nodeJS in 5 minutes
  • JavaScript binary tree and binary search tree implementation and application
  • With JavaScript and C3 to achieve a turntable small game
  • Teach you to use 200 lines of code to write a love bean spell H5 small game (with source code)
  • Exploration and summary of front-end integrated solutions based on React/VUE ecology
  • How to write your own JS library in less than 200 lines of code
  • A picture shows you how to play vue-Cli3 quickly
  • 3 minutes teach you to use native JS implementation with progress listening file upload preview component
  • Developing travel List with Angular8 and Baidu Maps API
  • Js basic search algorithm implementation and 1.7 million data under the performance test
  • How to make front-end code 60 times faster
  • Vue Advanced Advanced series – Play with Vue and vuex in typescript