Ecma TC39 has updated the ECMAScript standard once a year in recent years. The following features are finished. Now let’s experience the new features of ES2020.
A: Promise. AllSettled
Promise. All defects
Promise.all is known to have the ability to execute asynchronous tasks concurrently. The biggest problem with this is that if one of the tasks fails, all the tasks hang, and the Promise goes straight into reject.
Picture this: Use Promise. All to consign three interfaces. If any of the interfaces fails, reject will render all of the data in the three regions of the page. Since any reject goes into a catch callback, this is clearly unacceptable, as follows:
Promise.all([
Promise.reject({code: 500, msg: 'Service exception'}), Promise.resolve({ code: 200, list: []}), Promise.resolve({code: 200, list: []})]).then((ret) => {// If one of the tasks is reject, the callback is not executed. RenderContent(ret); }). Catch ((error) => {// error: {code: 500, MSG:"Abnormal service"}})Copy the code
This is a big pity or pity. We need a mechanism. If a concurrent task is fulfilled, no matter the task is normal or abnormal, the corresponding state (depressing or rejected) and result (business value or reason) will be returned. In then, the desired business logic results can be filtered by filter, which maximizes the accessibility of the current state of the business. Promise.allsettled is the solution to this problem.
Promise.allSettled([
Promise.reject({code: 500, msg: 'Service exception'}),
Promise.resolve({ code: 200, list: []}),
Promise.resolve({code: 200, list: []})
])
.then((ret) => {
/*
0: {status: "rejected"Reason: {... }} 1: {status:"fulfilled", the value: {... }} 2: {status:"fulfilled", the value: {... RenderContent(ret. Filter ((el) => {}} */ / Filter out the rejected state, RenderContent(ret. Filter (el) => {returnel.status ! = ='rejected';
}));
});
Copy the code
2: Optional Chaining
Optional chains allow us to query multi-tiered objects without the need for redundant pre-validation.
In daily development, we often encounter such queries
var name = user && user.info && user.info.name;
Copy the code
Or this
var age = user && user.info && user.info.getAge && user.info.getAge();
Copy the code
Uncaught TypeError: Cannot read property Uncaught TypeError: Cannot read property… This kind of error, this is very likely to kill your entire application.
With Optional Chaining, the above code becomes
var name = user? .info?.name;Copy the code
var age = user? .info?.getAge?.();Copy the code
Optional chain? Indicates that if the expression to the left of the question mark has a value, the field following the question mark continues to be queried. As can be seen from the above, using the optional chain can greatly simplify the similar tedious pre-check operation, and it is safer.
3. Nullish coalescing Operator
When we query for an attribute, we often encounter that a default value is set if the attribute is not available. For example, query the player level in the following code.
var level = user.data.level || 'No level yet';
Copy the code
In JS, an empty string, 0, is automatically converted to false when the logical operator is evaluated. In the above code, if the player level itself is level 0, the variable level will be assigned a string with no level. This is a logical error.
/ / {/ /"level": null // } var level = user.level ! == undefined && user.level ! == null ? user.level :'No level yet';
Copy the code
Let’s see what happens with the null-value merge operator. Okay
/ / {/ /"level": 0
// }
var level = user.level ?? 'No level yet'; // level -> 0
// {
// "an_other_field": 0
// }
var level = user.level ?? 'No level yet'; // level -> 'No level yet'
Copy the code
With null value merge operation in the premise of correct logic, the code is more concise.
The null-value merge operator, combined with optional chains, makes it easy to handle multi-level queries and assign defaults.
var level = user.data? .level ??'No level yet';
Copy the code
4: dynamic – the import
The On-demand import proposal has been around for a few years now, and is finally making it into the FORMAL ES specification. “On demand” is more appropriate. Modern front-end packaging resources are increasing, packaging into several M JS resources has become a normal, but often front-end application initialization does not need to load the full logical resources, in order to speed up the first screen rendering, many times are loaded on demand, such as lazy loading images. The on-demand logic resources are loaded in an event callback.
el.onclick = () => { import(`/path/current-logic.js`) .then((module) => { module.doSomthing(); }) .catch((err) => { // load error; })}Copy the code
Of course, WebPack now has good support for this feature.
Five: globalThis
Javascript has different ways of retrieving global objects in different environments, such as node via global, Web via Window, self, etc. Some even get global objects through this, but this is extremely dangerous, this is extremely complex in JS, It relies heavily on the current execution context, which undoubtedly increases the complexity of obtaining global objects.
In the past, global objects can be obtained through a global function
var getGlobal = function () {
if(typeof self ! = ='undefined') { return self; }
if(typeof window ! = ='undefined') { return window; }
if(typeof global ! = ='undefined') { return global; }
throw new Error('unable to locate global object');
};
var globals = getGlobal();
// https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/globalThis
Copy the code
The purpose of globalThis is to provide a standardized way to access global objects. With globalThis, you can access global objects in any context at any time.
Six: BigInt
In Js, the Number type can only safely represent values from -(2^53-1) to 2^53-1, that is, number. MIN_SAFE_INTEGER to number. MAX_SAFE_INTEGER.
var num = Number.MAX_SAFE_INTEGER; // -> 9007199254740991 num = num + 1; Num = num +1; 9007199254740992 9007199254740992 // Two different values, but returnedtrue
9007199254740992 === 9007199254740993 // -> true
Copy the code
To solve this problem, ES2020 provides a new data type: BigInt. There are two ways to use BigInt:
- Add after the integer literal
n
.
var bigIntNum = 9007199254740993n;
Copy the code
- use
BigInt
Function.
var bigIntNum = BigInt(9007199254740);
var anOtherBigIntNum = BigInt('9007199254740993');
Copy the code
With BigInt, we can safely compute large integer types.
var bigNumRet = 9007199254740993n + 9007199254740993n; // -> -> 18014398509481986n
bigNumRet.toString(); // -> '18014398509481986'
Copy the code
Note:
- BigInt is a new type of primitive.
typeof 9007199254740993n; // -> 'bigint'
Copy the code
- Avoid calling functions whenever possible
BigInt
Method to instantiate a large integer. Because the parameter literal is actually an instantiation of type Number, numbers outside the safe range can cause loss of precision.
Seven: String. Prototype. MatchAll
Consider the following code
var str = '< text > javascript < / text > < text > regular < / text >'; var reg = /<\w+>(.*?) <\/\w+>/g; console.log(str.match(reg)); / / - > ["<text>JS</text>"."< text > regular < / text >"]
Copy the code
It can be seen that the returned array contains the parent match, but does not match the child (group). Try removing the global search “g”.
var str = '< text > javascript < / text > < text > regular < / text >'; Var reg = /<\w+>(.*?) <\/\w+>/; console.log(str.match(reg)); // It will print /* ["<text>JS</text>"."JS",
index: 0,
input:
"< text > javascript < / text > < text > regular < / text >",
groups: undefined
]
*/
Copy the code
This gets the parent of the match, including the child (group), but only the first matching character. You can see that the
re
What if I get all of the global matches, including the children?
ES2020 provides a simple way: String. Prototype. MatchAll, this method returns an iterator.
var str = '< text > javascript < / text > < text > regular < / text >'; var allMatchs = str.matchAll(/<\w+>(.*?) <\/\w+>/g);for(const match of allMatchs) { console.log(match); } /* The first iteration returns: ["<text>JS</text>"."JS",
index: 0,
input: "< text > javascript < / text > < text > regular < / text >", groups: undefined]"< text > regular < / text >"."Regular",
index: 15,
input: "< text > javascript < / text > < text > regular < / text >",
groups: undefined
]
*/
Copy the code
You can see that all matches are available in each iteration, as well as some additional meta information about the success of the match.
The resources
- Github.com/tc39/propos…
- prop-tc39.now.sh/