1, let, const, var
Let is used similarly to var, but only within a code block, so we usually use let instead of var within a code block. Instead, use const to declare constants.
A declarative way | Variable ascension | Temporary dead zone | Repeat statement | The initial value | scope |
---|---|---|---|---|---|
var | allow | There is no | allow | Don’t need | In addition to the block-level |
let | Don’t allow | There are | Don’t allow | Don’t need | block-level |
const | Don’t allow | There are | Don’t allow | Don’t need | block-level |
1.1. Variable promotion
Variables can be used before declaration.
// Variable promotion console.log(a); //undefined var a = 1; console.log(b); //ReferenceError: b is not defined let b = 1; console.log(c); //ReferenceError: c is not defined const c = 1;Copy the code
The var command often promotes variables. Logic dictates that variables should be used after they have been declared. To correct this, ES6 states that let and const commands do not promote variables, and that variables are not available until they are declared using let and const commands. The main purpose is to reduce runtime errors and prevent unexpected behavior by using a variable before it is declared.
1.2. Temporary dead zone
If there are let or const commands in a code block, the block is closed scoped from the start for the variables declared by those commands. Any time these variables are used before declaration, an error is reported.
var tmp = 123; if (true) { tmp = 'abc'; // ReferenceError: TMP is not defined let TMP; }Copy the code
The original intention of this code is to define external TMP as’ ABC ‘within if.
In reality, the global variable TMP exists, but in the block-level scope, let declared another TMP variable, causing the latter to be bound to the block-level scope, so the assignment to TMP was reported as an error before let declared the variable.
1.3. Repeated declarations
To declare the same variable repeatedly in the same scope.
The let and const commands do not allow variables to be declared twice:
function func(){ let a = 10; Const PI = 3.1415; var a = 1; // declared error, Uncaught SyntaxError: Identifier 'a' has already been declared var PI = 3; // declare error, Uncaught SyntaxError: Identifier 'PI' has already been declared} // declare error when calling func(), Uncaught SyntaxError: Identifier 'a' has already been declared function func(){ let a = 10; Const PI = 3.1415; let a = 1; // declare const PI = 3; // declare const PI = 3; // declare error, Uncaught SyntaxError: Identifier 'PI' already been declared}Copy the code
Var allows for repeated definitions, and where does that get us in trouble?
var i = 10; for(var i = 0; i < 5; i++){ console.log(i); } console.log(i); / / output 5Copy the code
For those of you who have learned static (typed) languages, this code, if replaced with C or some other static language, should yield 10. For javascript, however, the output of this code is 5. Because the var command has no block-level scope, the variable I in the parentheses of the for loop overwrites the outer I, and var allows repeated declarations, so I is declared twice and the result of I is overwritten by the I of the for loop.
1.4. Initial value
Because a const is a read-only constant, it must be initialized immediately after it is declared and cannot change its value. (Note: immutable means the address in memory is immutable)
Const PI = 3.1415; PI = 3; // Const definition of a variable is not constant, is not immutable, // it defines a constant reference to a value. // The essence of immutable is that addresses in memory cannot be changed // objects or arrays defined by const are mutable. Const b ={} b.m=123 console.log(b.m) //123 b.m=456 console.log(b.m) //456 b.o={k:789} b.o={k:125} console.log(b.o) //{ k: 125 } b ={} //Assignment to constant variable. Reference values cannot be changedCopy the code
1.5. Scope
In ES5, there are only global and functional scopes, not block-level scopes, which leads to a lot of irrational scenarios.
In the first scenario, the inner variables may override the outer variables.
var tmp = new Date(); // in the global scope function f() {console.log(TMP); // in function scope if (false) {var TMP = 'hello world'; } } f(); // undefinedCopy the code
The if block uses the TMP variable in the outer layer and the TMP variable in the inner layer. However, in this code, the two TMP variables inside function are in the same function scope. Due to the variable promotion, TMP in function scope overwrites TMP in global scope, so the output result of f() is undefined.
In the second scenario, loop variables used to count are exposed as global variables (mentioned earlier in the repeat declaration) :
var i = 10; for(var i = 0; i < 5; i++){ console.log(i); } console.log(i); / / output 5Copy the code
In the code above, the variable I is used only to control the loop, but when the loop ends, it does not disappear and leaks out as a global variable.
2. Deconstruct assignment
It is a method of pattern matching for arrays or objects, and then assigning values to the variables in them.
Concise and easy to read in code writing, more clear semantics; It also facilitates data field retrieval in complex objects.
var person = {
name:'jerry',
age:22
}
const {name ,age } = person
console.log(name) //jerry
console.log(age) //22
console.log(a) //undefined
console.log(b) //undefined
Copy the code
3, symbol
A new primitive data type, Symbol, represents a unique value. The largest use is to define the unique attribute name of an object.
The Symbol stack cannot use the new command because Symbol is a primitive data type, not an object. You can take a string as an argument to provide a description of the newly created Symbol that can be displayed on the console or used as a string for easy differentiation.
let sy = Symbol("KK"); console.log(sy); // Symbol(KK) typeof(sy); Let sy1 = symbol ("kk"); sy === sy1; // falseCopy the code
3.1 Application Scenarios
As an attribute name
Since the value of each Symbol is not equal, Symbol is used as the attribute name of the object to ensure that the attributes are not identical.
Writing:
let sy = Symbol("key1"); // let syObject = {}; syObject[sy] = "kk"; console.log(syObject); / / {Symbol (key1) : "kk"} / / writing 2 let syObject = {(sy) : "kk"}; console.log(syObject); / / {Symbol (key1) : "kk"} / / writing 3 let syObject = {}; Object.defineProperty(syObject, sy, {value: "kk"}); console.log(syObject); // {Symbol(key1): "kk"}Copy the code
Symbol cannot be used as the name of an object property. Operator, square brackets. Because the. Operator is followed by a string, we get the string sy property instead of the Symbol sy property.
When the Symbol value is used as the attribute name, the attribute is public, not private, and can be accessed outside the class. But not in the for… In, for… Of the loop, will not be the Object. The keys (), Object. GetOwnPropertyNames () returns. If you want to read to the Symbol attribute of an Object, you can through the Object. The getOwnPropertySymbols () and Reflect ownKeys () to get.
Define constants
Using Symbol to define constants ensures that the values of the set of constants are not equal.
Used in switch case
For () with a 3.2, Symbol.
Symbol.for() is similar to the singleton pattern. First, the global search is performed to see if the registered Symbol has the Symbol value of the string parameter as the name. If so, the Symbol value is returned. And registered in the global environment for search.
let yellow = Symbol("Yellow");
let yellow1 = Symbol.for("Yellow");
yellow === yellow1; // false
let yellow2 = Symbol.for("Yellow");
yellow1 === yellow2; // true
Copy the code
3.3, Symbol. KeyFor ()
Symbol.keyfor () returns the key of a registered Symbol type value, which checks whether the Symbol value for the name of the string parameter has been registered.
let yellow1 = Symbol.for("Yellow");
Symbol.keyFor(yellow1); // "Yellow"
Copy the code
4, the Map
Map objects hold key-value pairs. Any value (object or raw value) can be a key or a value.
4.1 Differences between Maps and Objects
- An Object key can only be a string or a symbol, but a Map key can be any value.
- Keys in a Map are ordered (FIFO), while keys added to objects are not.
- The number of key-value pairs for Map can be obtained from the size property, whereas the number of key-value pairs for Object can only be calculated manually.
- An Object has its own prototype, and the key name on the prototype chain may conflict with the key name you set on the Object.
var myMap = new Map(); var keyString = "a string"; Mymap.set (keyString, "value associated with key 'a string' "); myMap.get(keyString); Mymap.get ("a string"); mymap.get ("a string"); // "Value associated with key 'a string'"Copy the code
The map key can be a string, object, or function
4.2 Iteration of Map
for… of
var myMap = new Map(); myMap.set(0, "zero"); myMap.set(1, "one"); <! -- Two logs will be displayed. For (var [key, value] of myMap) {console.log('1',key + "=" + value); } /* 1 0 = zero 1 1 = one */ /* The entries method returns a new Iterator containing the [key, value] array of each element in the Map in insertion order. */ for (var [key, value] of myMap.entries()) { console.log('2',key + " = " + value); } /* 2 0 = zero 2 1 = one */ /* The keys method returns a new Iterator containing the keys of each element in the Map in insertion order. */ for (var key of myMap.keys()) { console.log('3',key); } /* 3 0 3 1 */ /* The values method returns a new Iterator containing the values of each element in the Map in insertion order. */ for (var value of myMap.values()) { console.log('4',value); } /* 4 zero 4 one */Copy the code
forEach()
var myMap = new Map(); myMap.set(0, "zero"); myMap.set(1, "one"); // Two logs will be displayed. Mymap.foreach (function(value, key) {console.log(key + "=" + value); })Copy the code
4.3 Operations on Map Objects
Map and Array conversion
var kvArray = [["key1", "value1"], ["key2", "value2"]]; Var myMap = new Map(kvArray); var myMap = new Map(kvArray); Var outArray = array. from(myMap); // Use array. from to convert a Map object to a two-dimensional Array of key-value pairs. console.log(outArray) //[ [ 'key1', 'value1' ], [ 'key2', 'value2' ] ] console.log(kvArray) //[ [ 'key1', 'value1' ], [ 'key2', 'value2' ] ] console.log(myMap) //Map { 'key1' => 'value1', 'key2' => 'value2' }Copy the code
The Map of cloning
var myMap1 = new Map([["key1", "value1"], ["key2", "value2"]]); var myMap2 = new Map(myMap1); console.log(myMap1 === myMap2); / / false. The Map object constructor generates instances and iterates out new objects.Copy the code
The Map of merger
var first = new Map([[1, 'one'], [2, 'two'], [3, 'three'],]); var second = new Map([[1, 'uno'], [2, 'dos']]); Uno, DOS, three var merged = new Map([...first,...second]); // Merge Map object uno, DOS, three var merged = new Map([...first,...second]); // Merge Map object uno, DOS, three var merged = new Map([...first,...second]); console.log(first) //Map { 1 => 'one', 2 => 'two', 3 => 'three' } console.log(second) //Map { 1 => 'uno', 2 => 'dos' } console.log(merged) //Map { 1 => 'uno', 2 => 'dos', 3 => 'three' }Copy the code
4.4, WeakMap
WeakMap structure is similar to Map structure and is also used to generate a set of key-value pairs. The difference is that WeakMap does not prevent its key values from being garbage collected. That means you can associate data with objects without worrying about memory leaks.
5, Set
The Set object allows you to store a unique value of any type, either a primitive value or an object reference.
5.1. Special values in Set
A Set object stores a value that is always unique, so you need to determine whether two values are identical. There are several special values that require special treatment:
- +0 and -0 are identical in the storage of judgment uniqueness, so they are not repeated;
- Undefined and undefined are identical, so do not repeat;
- NaN is not identical to NaN, but only one can be stored in a Set.
let mySet = new Set(); console.log(mySet.add(1)); // Set {1} console.log(mySet.add(5)); // Set {1, 5} console.log(mySet.add(5)); Console. log(myset.add ("some text")); // Set {1, 5} console.log(myset.add ("some text")); // Set {1, 5, "some text"} var o = {a: 1, b: 2}; console.log(mySet.add(o)); //Set { 1, 5, 'some text', { a: 1, b: 2 } } console.log(mySet.add({a: 1, b: 2})); Set {1, 5, 'some text', {a: 1, b: 2}, {a: 1, b: 2}, {a: 1, b: 2}Copy the code
5.2. Type Conversion
Var mySet = new Set(["value1", "value2", "value3"]); The console. The log (mySet) / / Set {' value1 ', 'value2', 'value3'} / / with... Var myArray = [...mySet]; Console. log(myArray) //['value1', 'value2', 'value3'] var mySet = new Set('hello'); Console. log(mySet) //Set {'h', 'e', 'l', 'o'} //Copy the code
5.3. Function of SET
Array to heavy
var mySet = new Set([1, 2, 3, 4, 4]);
console.log([...mySet]); // [1, 2, 3, 4]
Copy the code
And set
var a = new Set([1, 2, 3]);
var b = new Set([4, 3, 2]);
var union = new Set([...a, ...b]); // {1, 2, 3, 4}
Copy the code
intersection
var a = new Set([1, 2, 3]); var b = new Set([4, 3, 2]); var intersect = new Set([...a].filter(x => b.has(x))); / / {2, 3}Copy the code
Difference set
var a = new Set([1, 2, 3]); var b = new Set([4, 3, 2]); var difference = new Set([...a].filter(x => ! b.has(x))); / / {1}Copy the code
.filter is a built-in iteration method that takes an assertion function that is called on each array member of the iteration, filtering out (that is, keeping) the member if the function returns a true value, and filtering out (false) the member otherwise. Finally,.filter returns a subset of the original array.
5.4, WeakSet
WeakSet structure is similar to Set, which is also a collection of non-repeating values. However, it differs from Set in two ways.
- WeakSet members can only be objects, not other types of values.
- WeakSet objects are weak references, that is, garbage collection mechanism does not consider WeakSet’s reference to the object, that is, if other objects no longer reference the object, then garbage collection mechanism will automatically recover the memory occupied by the object, not considering the object still exists in WeakSet.
The Set with the Map
In the process of use, the obvious Set and Map have obvious convenience advantages over the Array and Object that we often use before.
In the subsequent development process, we can use Set and Map instead of Array and Object according to the needs of the scene.
If you have a need to store unique data structures, consider using sets.
If the data is complex, consider using a Map. Some build tools prefer to use this data structure for configuration because it is flexible, efficient, and suitable for one-to-one lookup.
A Set has a similar API to a Map, the main difference being that a Set does not have a Set method because it cannot store key-value pairs, leaving almost the same.
Reflect and Proxy
The Proxy intercepts operations such as reading and function invocation of the target object, and then processes the operations. It does not operate directly on objects, but rather acts like a proxy mode, operating through objects’ proxy objects, and as it does so, additional operations can be added as needed.
Reflect can be used to get the behavior of a target Object, which is similar to Object but more readable and provides a more elegant way to manipulate objects. Its methods correspond to Proxy.
proxy
A Proxy object consists of two parts: target and handler. These two parameters are required when generating the instance object through the Proxy constructor. Target is the target object, and handler is an object that declares the specified behavior of the proxy target.
let target = { name: 'Tom', age: 24 } let handler = { get: function(target, key) { console.log('getting '+key); return target[key]; Key}, set: function(target, key, value) {console.log('setting '+key); target[key] = value; } } let proxy = new Proxy(target, Handler. get proxy.age = 25 // Handler. set // getting name // setting age // proxy Is a shallow copy of target console.log(target.age) //25Copy the code
reflect
ES6 migrates some of Object’s methods that are clearly internal to the language to Reflect (some methods currently exist on both Object and Reflect), and future new methods will be deployed only on Reflect.
Reflect.get(target, name, receiver)
Finds and returns the name property of the target object
let exam = { name: "Tom", age: 24, get info(){ return this.name + this.age; } } Reflect.get(exam, 'name'); // receiver let receiver = {name: "Jerry", age: 20 } Reflect.get(exam, 'info', receiver); // Reflect. Get (exam, 'birth'); // Jerry20 // Undefined reflect. get(exam, 'birth'); // undefined // Reflect. Get (1, 'name'); // TypeErrorCopy the code
Reflect.set(target, name, value, receiver)
Set target’s name property to value. The return value is Boolean, true means the modification succeeded, false means the modification failed. An error is reported when target is an object that does not exist.
let exam = { name: "Tom", age: 24, set info(value){ return this.age = value; } } exam.age; // 24 Reflect.set(exam, 'age', 25); // true exam.age; // Reflect. Set (exam, 'age',); // true exam.age; // undefined // when the target object has a setter for the name property, This in setter methods is bound to // receiver, so it is actually the property of receiver that is modified. Let receiver = {age: 18 } Reflect.set(exam, 'info', 1, receiver); // true receiver.age; // 1 let receiver1 = { name: 'oppps' } Reflect.set(exam, 'info', 1, receiver1); receiver1.age; / / 1Copy the code
Reflect.has(obj, name)
Is a functionalization of the name in obj directive that looks for the presence of the name attribute in an obj object. The return value is Boolean. TypeError is reported if obj is not an object.
let exam = {
name: "Tom",
age: 24
}
Reflect.has(exam, 'name'); // true
Copy the code
Reflect.deleteProperty(obj, property)
let exam = { name: "Tom", age: 24 } Reflect.deleteProperty(exam , 'name'); // true exam // {age: 24} // If the property does not exist, it will return true Reflect.deleteProperty(exam, 'name'); // trueCopy the code
Reflect.ownKeys(target)
To return all attributes of the target Object is the same as the Object, getOwnPropertyNames with Object. GetOwnPropertySymbols combined.
var exam = {
name: 1,
[Symbol.for('age')]: 4
}
Reflect.ownKeys(exam) // ["name", Symbol(age)]
Copy the code
Use a combination of
The methods of the Reflect object correspond to those of the Proxy object. So the Proxy object’s method can get the default behavior by calling the Reflect object’s method and then do something extra.
let exam = {
name: "Tom",
age: 24
}
let handler = {
get: function(target, key){
console.log("getting "+key);
return Reflect.get(target,key);
},
set: function(target, key, value){
console.log("setting "+key+" to "+value)
Reflect.set(target, key, value);
}
}
let proxy = new Proxy(exam, handler)
proxy.name = "Jerry"
proxy.name
// setting name to Jerry
// getting name
// "Jerry"
Copy the code
7. Template string
Using a lot of “” (double quotes) and + concatenation to get the template we need. Template strings allow a more elegant way to concatenate strings that is less error-prone
`string text ${expression} string text`
Copy the code
8, objects,
Object. The assign (target, source_1,…)
Use to copy all enumerable properties of the source object into the target object.
If the target object and the source object have an attribute with the same name, or if multiple source objects have an attribute with the same name, the later attribute overrides the previous one.
Object.is(value1, value2)
Used to compare whether two values are strictly equal, similar to (===).
The difference between:
Object. Is (+0,-0); //false +0 === -0 //true // //true NaN === NaN //falseCopy the code
9, arrays,
Array.of()
Forms an array of all the values of a parameter as elements.
console.log(Array.of(1, 2, 3, 4)); / / [1, 2, 3, 4] / / parameter values for different types of the console, log (Array) of (1, '2', true)); // [1, '2', true] // Returns an empty Array console.log(array.of ()) if the argument is null; / / []Copy the code
Array.from()
Convert an array-like object or iterable to an array
Console. log(array. from([1, 2]))); / / / / [1, 2] parameters including open the console, log (Array) from ([1, 3])); // [1, undefined, 3]Copy the code
10. Extend operators
Spread operator (spread)(form:…) , sort of like the inverse of the REST argument, turns an array into a comma-separated sequence of arguments.
Var arr = [1,2,3,4,5,6] console.log(... arr) //1 2 3 4 5 6Copy the code
Application Scenarios:
- Deconstruction assignment
Const [a, b, c...] = [6]. The console log / / 1 (a) the console. The log / / 2 (b) the console. The log (c) / / [3, 4, 5, 6 ] const {name,age,... F} = {name: jerry, age: 22, some: true, another: 'sda} the console. The log (name) must be the name / / jerry console. The log must be age (age) / / 22 console.log(f) //{ some: true, another: 'sda' }Copy the code
- Merge arrays, objects
Var arr1 = [1, 2, 3] var arr2 = [three, four, five] var arr = [arr1,... arr2] the console. The log (arr) / / [1, 2, 3, 3, 4, 5 ] var obj1 = { name:'jerry', age:22 } var obj2={ school:'hebeigc', class:3 } var obj = {... obj1,... obj2} console.log(obj) //{ name: 'jerry', age: 22, school: 'hebeigc', class: 3 }Copy the code
- Help complete mapping of functions in VUEX
export default new Vuex.Store({ state: { list: [], inputValue: '' }, mutations: { setInput(state, inpVal) { state.inputValue = inpVal } }, actions: { async getList(context) { const { data: res } = await axios.get('/list.json') context.commit('initList', res) } }, getters: UnDone (state) {const unDoneList = state.list.filter(item => {return item.done === false}) return 'unDone' + Undonelist. length + 'bar'}})Copy the code
Import {mapState, mapMutations, mapActions, mapGetters} from 'vuex' export default {name: 'app', data() { return {} }, methods: { ... mapMutations(['setInput']), ... mapActions(['getList']), }, computed: { ... mapState(['inputValue']), ... mapGetters(['unDone']) } }Copy the code
The mapMutations and mapActions functions map the functions specified in mutations and Actions to the methods functions of the current component.
The mapState and mapGetters functions map global data in state to computed properties of the current component.
- Shallow copy
Var obj = {: o {a: 1}, arr: [1, 2]} var clonObj = {... obj} console.log(clonObj) //{ o: { a: 1 }, arr: [ 1, 2 ] } clonObj.o.a=5; clonObj.arr[0]=5 console.log(obj) //{ o: { a: 5 }, arr: [ 5, 2 ] } console.log(clonObj) //{ o: { a: 5 }, arr: [ 5, 2 ] }Copy the code
11. The rest parameters
The rest argument is an array that contains an unknown number of extra arguments to the function (unlimited length)
let {a, b, ... rest} = {a: 10, b: 20, c: 30, d: 40}; // a = 10 // b = 20 // rest = {c: 30, d: 40}Copy the code
Used to solve arrow functions without arguments problems.
Function arg(){console.log(arguments) console.log(arguments[0]) //1} arg(1,2,3,4,5,6) //[arguments] {'0': 1, '1': 2, '2': 3, '3': 4, '4': 5, '5': 6 } const args=(... Console. log('rest',rest) //[1,2,3,4,5]} args(1,2,3,4,5)Copy the code
The arguments and… rest:
Function cb(a,b){} Function cb(a,b){} Function cb(a,b){} Function cb(a,b... Rest){} The rest of the arguments are in the REST arrayCopy the code
10. Arrow function
(function(){
console.log([
(()=>this.x).bind({x:'in'})(),
(()=>this.x)()
])
}).call({x:'ourter'})
// [ 'ourter', 'ourter' ]
Copy the code
var id = 1 const o = { id: 2, m() { console.log('m--->', this.id) }, n: () => { console.log('n--->', This.id)}} o.m() // 2 points to o.n() // 1 points to window let p = o.p () // 1 points to window p = o.p () // 1 points to windowCopy the code
var id = 1 const o = { id: 2, m() { console.log('m--->', this.id) }, n: function () { return () => { console.log('n--->', This. Id)}}} o.m () / / 2 point o o.n () () / / 2 points to let p = o o.m window p = p () / / 1 point to o.n () p () / / 2 point p = o o.n p () () / / 1 Pointing to the oCopy the code
The arrow function this depends on the scope in which it is defined. Other functions this depend on the runtime scope
The arrow function does not create its own this; it only inherits this from the upper level of its scope chain
11, class class
Module 12
13, promise
The Promise object is a constructor that generates a Promise instance. The state of the object is not affected by the outside world. Only the result of the asynchronous operation can determine the current state. This is a pity (对 话), which is pending(对 话), and rejected(对 failure). After the instance is generated, the then method specifies the Resolved and Rejected state callback functions, respectively
The chain call to Promise
You can continue writing the Promise object in THEN and return it, and then continue calling the THEN for the callback
Let’s start with some code:
New Promise((resolve, reject) => {console.log("log: external Promise "); resolve(); }). Then (() => {console.log("log: external first then"); New Promise((resolve, reject) => {console.log("log: internal Promise "); resolve(); }). Then (() => {console.log("log: internal first then"); }). Then (() => {console.log("log: internal second then"); }); }). Then (() => {console.log("log: external second then"); }); // log: external promise // log: external first then // log: internal second then // log: internal second thenCopy the code
conclusion
-
When the THEN method is executed, if the earlier promise is resolved, the callback is put directly into the microtask queue
When the THEN method is executed synchronously, a judgment is made:
-
If the earlier promise is resolved, the callback will be pushed to the microtask queue immediately (but not until all synchronization tasks have finished)
-
If the previous promise is pending, the callback is stored inside the promise and pushed into the microtask queue until the promise is resolved
-
-
When a promise is resolved, all callbacks previously registered for that promise through THEN are iterated over and placed in the microtask queue in turn
To understand all the callbacks registered for this promise through THEN, consider the following example
let p = new Promise((resolve, reject) => { setTimeout(resolve, 1000); }); P.teng (() => {console.log("log: external first then"); }); P.teng (() => {console.log("log: external second then"); }); P.teng (() => {console.log("log: external third then"); });Copy the code
The variable p will not be resolved until 1 second later, but three callbacks are registered with the then method before resolve. These callbacks will not be executed and will not be placed in the microtask queue. They will be stored internally by P (when writing a promise, These callbacks will be stored in the promise’s internal array). After P is resolved, the three callbacks will be pushed into the microtask queue one by one. If there is no synchronization task, the three callbacks will be fetched and executed.
-
Then must return a Promise instance (to push the next then-registered callback to the microtask queue via resolve)
There is no resolve function for a promise returned by the THEN method. Instead, the promise returned by the THEN method is resolved as soon as the code in the then callback completes and returns a synchronized value
In other words, if a callback in then returns a promise, the promise returned by then will wait until the promise is resolved
new Promise((resolve, reject) => { resolve(); }). Then (() => //1. Resolve new Promise((resolve, reject) => {resolve(); }). Then (() => {console.log("log: internal first then"); Resolve}). Then (() => {//4. The external first thenresolve pushes the callback registered by the external second THEN to the microtask queue console.log("log: external second THEN "); }); // log: internal first then // log: external second thenCopy the code
-
Resolve:
The resolve function is the first argument passed to the function when a Promise is instantiated
new Promise(resolve => { resolve(); }); Copy the code
In addition to changing the current promise from pending to Resolved, it will iterate through all the callbacks that were registered for that promise through THEN and place them in the microtask queue. Many people think it’s triggered by the THEN method to save the callback. In fact, the THEN method neither triggers the callback nor puts it on the microtask; then only registers the callback, which resolve places into the microtask queue, and the event loop retrieves and executes it.
-
Go back to the original example:
New Promise((resolve, reject) => {console.log("log: external Promise "); resolve(); }). Then (() => {console.log("log: external first then"); New Promise((resolve, reject) => {console.log("log: internal Promise "); resolve(); }). Then (() => {console.log("log: internal first then"); }). Then (() => {console.log("log: internal second then"); }); }). Then (() => {console.log("log: external second then"); }); // log: external promise // log: external first then // log: internal second then // log: internal second thenCopy the code
-
We start with the promise instantiation, log: external promise
-
The resolve function changes the initial promise state to Resolved
-
Execute the first external THEN function, and since the preceding Promise is resolved, push the callback function in that THEN directly to the microtask queue
- Main thread: the second external THEN function
- Microtask: External first THEN function
-
Execute the second THEN function outside the main thread, doing nothing because the preceding promise (the promise returned by the first THEN) is still pending.
- The main thread:
- Microtask: External first THEN function
-
Execute the first external THEN function in the microtask queue, log: the first external THEN, initialize the promise, log: the internal promise, resolve: the internal promise state changes to Resolved
-
Execute the first internal THEN function and push the callback of the first internal THEN function directly to the microtask queue because the previous Promise has resolved
- Main thread: internal second THEN
- Microtask: Internal first THEN
-
Execute the second internal THEN function on the main thread, and do nothing (register, do not advance, do not execute) because the preceding PROMISE (the first internal THEN) is still pending.
-
When the first external THEN function completes and the state becomes resolved, the callback registered for him will be pushed to the micro task queue using the second external THEN function.
- The main thread:
- Microtask: internal first THEN function, external second THEN function
-
Execute the first internal THEN function in the micro-task, log: the first internal THEN function is completed, the state becomes resolved, and his callback function (the second internal THEN) is pushed to the micro-task queue
- The main thread:
- Microtask: external second THEN function, internal second THEN function
-
Then execute the following order: log: external second THEN, log: internal second THEN
Promise common methods
Function func(){return new Promise(resolve,reject)=>{// resolve(data) or reject(err)})}Copy the code
-
Promise.then (success callback, failure callback)
func().then( (data) => { //resolve }, (err) => { //reject } ) Copy the code
-
Promise.then (success callback).catch(failure callback)
func().then( (data) => {//resolved} ).catch( (err) => { // reject} ) Copy the code
-
Promise.then (successful callback).catch(failed callback).finally(successful and failed function)
func().then( (data) => {//resolved} ).catch( (err) => { // reject} ).finally( (over) => {//all} ) Copy the code
-
promise.all([a1,a2,a3])
Promise.all can wrap multiple Promise instances into a new Promise instance. Also, success and failure return different values, with success returning an array of results and failure returning the first rejected state.
Promse.all is useful when dealing with multiple asynchronous processes, such as a page that needs to wait for two or more Ajax data returns before displaying only the Loading icon.
In particular, the order of the data in the array of the successful results obtained by Promise.all is the same as that received by Promise.all, that is, the result of P1 is first, even though the result of P1 is obtained later than p2. This has one great benefit: When developing request data on the front end, there are occasional scenarios where multiple requests are sent and the data is retrieved and consumed according to the order in which they are requested, using Promise.all is a surefire way to solve this problem.
Let p1 = new Promise((resolve, reject) => {resolve(" succeed "); }); let p2 = new Promise((resolve, reject) => { resolve("success"); }); Let p3 = promise.reject (" reject "); Promise.all([p1, p2]) .then((result) => { console.log(result); / / / 'success' and 'success'}). The catch ((error) = > {the console. The log (error); }); Promise.all([p1, p3, p2]) .then((result) => { console.log(result); }) .catch((error) => { console.log(error); // failed, type 'failed'});Copy the code
-
promise.race([a1,a2,a3])
Promse.race, as the name suggests, means a race, which means that a Promise. Race ([P1, P2, P3]) returns the fastest result, regardless of whether the result itself is a success or a failure.
let p1 = new Promise((resolve, reject) => { setTimeout(() => { resolve("success"); }, 1000); }); let p2 = new Promise((resolve, reject) => { setTimeout(() => { reject("failed"); }, 500); }); Promise.race([p1, p2]) .then((result) => { console.log(result); }) .catch((error) => { console.log('err-',error); // err- failed }); Copy the code
-
promise.resolve()
Resolve ('foo') // equivalent to new Promise(resolve => resolve('foo'))Copy the code
-
promise.reject()
Reject (reason) also returns a new Promise instance whose state is Rejected const p = promise.reject (' something went wrong '); // const p = new Promise((resolve, reject) => reject(' error ')) p.hen (null, function (s) {console.log(s) // error});Copy the code
async/await
What does async return
Take a look at the output of the following code:
Async function asyncReturn() {return 'async returns what? ' } var result = asyncReturn(); console.log(result); //Promise {'async 'returns what? '}Copy the code
The result shows that async returns a promise object. If async returns an immediate promise object in the function, async wraps the immediate promise object with promise.resolve ().
If async does not return a value:
async function testAsync1() {
console.log("hello async");
}
let result1 = testAsync1();
console.log(result1);
Copy the code
What processing does await do
‘await’ is literally waiting. ‘await’ is waiting for an expression whose return value can be a Promise object or other value.
Many people think that await is waiting for a subsequent expression to complete before continuing to execute code. In fact, await is a sign of relinquishing a thread. The function after await will execute once and then jump out of the whole async function to execute the code behind the JS stack. After the completion of this round of event loop, it will jump back to async function and wait for the return value of await expression. If the return value is non-promise, it will continue to execute the code behind async function. Otherwise, the returned promise will be put into promise Queue (promise Job Queue).
Async /await execution order
Function testSometing() {console.log("2- execute testSometing"); TestSometing return "5-testsometing "; } async function testAsync() {console.log("6- testAsync");} async function testAsync() {console.log("6- testAsync"); TestAsync return promise. resolve("8-hello async"); } async function test() {console.log("1-test start...") {console.log("1-test start...") ); //1--> print 1-- test start... const v1 = await testSometing(); //2--> execute testSometing() console.log(v1); //9--> print v1:5 -testting const v2 = await testAsync(); //10--> execute testAsync() console.log(v2); //14--> print 8-hello async console.log(v1, v2); //15--> print 5-testting, 8-hello async, end} test(); Var promise = new promise ((resolve)=> {//5--> execute promise console.log("3 -- promise start..") ); //6--> print 3- Promise start.. resolve("7-promise"); }); Promise.then ((val)=> console.log(val)); Return test() console.log("4-test end..."); ) //8--> print 4 -- test end... This event loop ends and jumps back to async function test().Copy the code
Add seTimeout to see what happens:
async function async1() { console.log("async1 start"); await async2(); console.log("async1 end"); }; async function async2() { console.log( 'async2'); }; console.log("script start"); setTimeout(function () { console.log("settimeout"); }, 0); async1(); new Promise(function (resolve) { console.log("promise1"); resolve(); }).then(function () { console.log("promise2"); }); console.log('script end');Copy the code
Await allows unfinished code behind a thread to perform a microtask after completion of execution.
Here’s another example:
var a = 0
var b = async () => {
a = a + await 10
console.log('2', a) // -> '2' 10
a = (await 10) + a
console.log('3', a) // -> '3' 20
}
b()
a++
console.log('1', a) // -> '1' 1
Copy the code
Output result:
1, 1, 2, 10, 3, 20Copy the code
Resolution:
- The first function
b
Execute first, and then execute toawait 10
Before the variablea
It’s still 0, because atawait
Internally implementedgenerators
,generators
It’s going to keep stuff in the stack, so at this pointa = 0
It’s been preserved - because
await
Is an asynchronous operation encounteredawait
It immediately returns onepending
The state of thePromise
Object that temporarily returns control of executing code, allowing code outside the function to continue execution, so it executes firstconsole.log('1', a)
- When the synchronous code is finished, the asynchronous code is executed, and the saved value is taken out for use
a = 10
- And then the regular execution code
Ding, ding, ding!! Welcome to search for “front-end handwriting” or scan code on wechatPay attention to wechat public number, we make progress together.