ES2020 is the equivalent version of ECMAScript for 2020

String.protype.matchAll

Scene:

  • Gets a match for a substring in the original string
  • And the subscript position of the matching term
  • Re matches grouped in the original string

Previously it could only be retrieved through the regex.exec loop

Note: ‘/g’ must be added to the re otherwise an error will be reported

The old / /
var regex = /t(e)(st(\d?) )/g;
var string = "test1test2test3";

var matches = [];
var match;

// regex.exec executes one less time
while ((match = regex.exec(string))) {
  matches.push(match);
}

console.log(matches);
/ / /
// ["test1", "e", "st1", "1", index: 0, input: "test1test2test3"],
// ["test2", "e", "st2", "2", index: 5, input: "test1test2test3"],
// ["test3", "e", "st3", "3", index: 10, input: "test1test2test3"]
// ]
Copy the code

The matchAll() method returns all matches of a regular expression in the current string

However, it returns an Iterator, not an array. It is very simple to convert the iterator into an array, using… The operator and the array.from () method do the job.

const string = "test1test2test3";
const regex = /t(e)(st(\d?) )/g;

const newdata = string.matchAll(regex);

for (const match of newdata) {
  console.log(match);
}
// ["test1", "e", "st1", "1", index: 0, input: "test1test2test3"]
// ["test2", "e", "st2", "2", index: 5, input: "test1test2test3"]
// ["test3", "e", "st3", "3", index: 10, input: "test1test2test3"]

// Convert to array
[...newdata];

// Convert to array
Array.from(newdata);
Copy the code

Return value resolution

First determine how many groups there are based on the number of parentheses in the regular expression,

const regex = /t(e)(st(\d?) )/g There are three groups

  1. The first group:(e)
  2. The second group:(st(\d?) )
  3. The third group:(\d?)

[“test1”, “e”, “st1”, “1”, index: 0, input: “test1test2test3”]

  1. The first element of the array is the entire match.
  2. The second element is(e)Capture.
  3. The third element is the by(st(\d?) )Capture.
  4. The fourth element is the by(\d?)Capture.
  5. ‘index’ is the index for the entire match (step 1) from zero.
  6. The ‘input’ property is the raw string being parsed.

For details, see ES Introduction -matchAll

Dynamic import

Previously the import command was a static declaration. They accept string literals as module specifiers

Only at the top level of a module, not in a code block (for example, in an if code block, or in a function)

This design, while beneficial to the compiler’s efficiency, also makes it impossible to load modules at run time. Syntactically, conditional loading is not possible


The ES2020 proposal introduces import() to support dynamic loading of modules

The import(specifier) function supports dynamic module loading. The specifier parameter to import() specifies the location of the module to be loaded.

Import () accepts whatever arguments the import command accepts, the difference being that the latter is loaded dynamically.

Import () returns a Promise object

Import () can be used anywhere, not just for modules, but also for non-module scripts. It’s run time execution, which means, when do I get to this point, it loads the specified module

Usage scenarios

Load on demand:import()You can load a module when you need it.

const someVariable = "user";

import(`./some-modules/${someVariable}.js`)
  .then((module) = > {
    // Business logic
    module.loadPageInto(main);
  })
  .catch((err) = > {
    // Failed to load
  });
Copy the code

Conditional loading:import()Can be placed inifCode blocks, depending on the situation, load different modules.

if (condition) {
  import('moduleA').then(...) ; }else {
  import('moduleB').then(...) ; }Copy the code

Dynamic module path:import()Allows module paths to be generated dynamically.

import(f()) .then(...) ;Copy the code

See ES Getting Started -import for details

Promise.allSettled

There are four main methods in Promise.

name Description
Promise.allSettled 1. Wait until all instances return results, no matter whetherfulfilledorrejected, the instance will end

2. Sometimes, we don’t care about the result of asynchronous requests, only care about whether all requests end
Internet ES2020 βœ…
Promise.all 1. If any promise fails, the failed promise is returned.

2. When all asynchronous operations are successful, the promise is returned as an array
Internet ES2015 βœ…
Promise.race Whenever the state of any promise changes (whether it succeeds or fails), that promise is returned Internet ES2015 βœ…
Promise.any 1. If any promise succeeds, the successful promise is returned.

2. If all promises fail/reject, return a failed promise
Internet ES2021 βœ…

The promise.allsettled () method takes a set of Promise instances as parameters, wrapped as a new Promise instance. The wrapping of the instance will not end until all of these parameter instances have returned results, whether fulfilled or rejected

Sometimes, we don’t care about the result of asynchronous requests, only that all requests end. This is where the promise.allsettled () approach comes in handy


What does the word settled mean?

Stop, stop, stop, stop, stop, stop

This is fulfilled fulfilled when the promise is in a non-pending state, such as fulfilled or rejected. Then the promise would be settled


Here’s a scenario where you iterate through an array of Promises and want to return a new array with a status field (regardless of whether status represents a promise’s success or failure)

[{status: "rejected".reason: "SyntaxError: Unexpected token < in JSON at position 0"}, {status: "fulfilled".value: { success: true.data: "..."}},];Copy the code

If you use promise. all, you can only write a handler by hand

function reflect(promise) {
  return promise.then(
    (v) = > {
      return { status: "fulfilled".value: v };
    },
    (error) = > {
      return { status: "rejected".reason: error }; }); }const promises = [fetch("index.html"), fetch("https://does-not-exist/")];
const results = await Promise.all(promises.map(reflect));
const successfulPromises = results.filter((p) = > p.status === "fulfilled");
Copy the code

But Promise.allSettled already wrote this handler for us

async function test() {
  const promises = [fetch("./index.html"), fetch("https://does-not-exist/")];
  const results = await Promise.allSettled(promises);

  // Filter out successful requests
  const successfulPromises = results
    .filter((p) = > p.status === "fulfilled")
    .map((p) = > p.value);

  // Filter out the failed requests and output the cause
  const errors = results
    .filter((p) = > p.status === "rejected")
    .map((p) = > p.reason);

  console.log(errors);
}

test();
Copy the code

A more realistic scenario: turn off loading after the request ends

If you use promise. all, you also need to determine the execution result

const urls = [
  / *... * /
];
const requests = urls.map((x) = > fetch(x)); // Imagine some of these will fail, and some will succeed.

// Short-circuits on first rejection, all other responses are lost
try {
  await Promise.all(requests);
  console.log(
    "All requests have completed; now I can remove the loading indicator.",); }catch {
  console.log(
    "At least one request has failed, but some of the requests still might not be finished! Oops.",); }Copy the code

Use promise. alallsettlement directly

// We know all API calls have finished. We use finally but allSettled will never reject.
Promise.allSettled(requests).finally(() = > {
  console.log("All requests are over, and I don't care if it succeeds or fails.");
  // Disable the loading state
  removeLoadingIndicator();
});
Copy the code

globalThis

Obtaining this for different environments before ES2020 requires the following encapsulation

const getGlobalThis = () = > {
  // In the webworker or service worker
  if (typeofself ! = ="undefined") return self;

  // In the browser
  if (typeof window! = ="undefined") return window;

  / / the Node. Js
  if (typeof global! = ="undefined") return global;

  // A separate JavaScript shell
  if (typeof this! = ="undefined") return this;

  throw new Error("Unable to locate global object");
};
const theGlobalThis = getGlobalThis();

if (typeoftheGlobalThis.setTimeout ! = ="function") {
  // There is no setTimeout method in this environment!
}
Copy the code

Now, globalThis provides a standard way to get the globalThis object (which is the global object itself) in different environments.

if (typeofglobalThis.setTimeout ! = ="function") {
  // There is no setTimeout method in this environment!
}
Copy the code

See MDN-globalThis for details

Nullish Coalescing Operator

Reason: make up for the Boolean or operator (| |) will be an empty string, 0, NaN judgment is false value

// Cannot get an empty string,0,NaN
function checkReturn0(test) {
  return test || "666";
}

// It is a little troublesome
function checkReturn0(test) {
  returntest ! = =undefined&& test ! = =null ? test : "666";
}

test ?? "666"Equivalent to test! = =undefined&& test ! = =null ? test : "666"

// The final solution
function checkReturn() {
  return test ?? "666";
}
Copy the code

Null merge operator (??) Only if the left-hand side is zero

  • null
  • undefined

Null merge operator (??) Returns the value on the right

const baz = 0 ?? 42;
console.log(baz);
// expected output: 0
Copy the code
// 'null' check and default assignment
let test1 = null;
let test2 = test1 ?? "";

console.log("null check", test2); // Output an empty string ""
Copy the code
// 'undefined' checks and defaults to assignment
const test = undefined ?? "default";

console.log(test);
// expected output: "default"
Copy the code
// Return after comparison

/ / bad πŸ‘΄
let test;
function checkReturn() {
  if(! (test ===undefined)) {
    return test;
  } else {
    return callMe("test"); }}/ / better πŸ‘Ά
function checkReturn() {
  return test ?? callMe("test");
}
Copy the code

Note: with the logical or operator (| |), | | will be on the left operand is false value returns the right operand

The Boolean or operator (| |) only when the left side is:

  • Empty string:' 'or` `
  • NaN
  • 0
  • null
  • undefined

The Boolean or operator (| |) will return to the right of the value

var a = "" || 1;
/ / output 1
console.log(a);
Copy the code

Use the optional chain operator –? .

When looking for attribute values deep in the tree, it is usually necessary to check for the presence of intermediate nodes:

If you do not judge, you will throw an undefined variable error ❌

var street = user.address && user.address.street;
Copy the code

Similarly, many apis return an object or null/undefined, and may only want to extract attributes from the result if it is not null.

? .Also called chain judgment operator. It allows us to read property values deeply nested in the chain of objects without having to validate each reference. When the property does not exist, the expression stops evaluating and returns undefined

const travelPlans = {
  destination: "DC".monday: {
    location: "National Mall".budget: 200,}};/ / bad πŸ‘΄
const res =
  travelPlans &&
  travelPlans.tuesday &&
  travelPlans.tuesday.location &&
  travelPlans.tuesday.location.href;

/ / better πŸ‘Ά
/ / output is undefined
constres1 = travelPlans? .tuesday? .location? .href;Copy the code

In JS,?? Operators are called non-airfreight operators. If the first argument is not null/undefined (there are only two false values here, but the false values in JS include: Undefined undefined undefined undefined undefined undefined undefined undefined null object NULL, numeric 0, empty number NaN, Boolean false, empty string ”, don’t confuse) returns the first argument, otherwise returns the second argument. For instance,

null ?? 5; / / = > 5
3 ?? 5; / / = > 3
Copy the code

To the variable to set the default value, the commonly used before | | the Boolean or operator, for example,

const prevMoney = 1;
const currMoney = 0;
const noAccount = null;
const futureMoney = -1;
function moneyAmount(money) {
  return money || 'Account not open';
}
console.log(moneyAmount(prevMoney)); / / = > 1
console.log(moneyAmount(currMoney)); // => The account is not open
console.log(moneyAmount(noAccount)); // => The account is not open
console.log(moneyAmount(futureMoney)); / / = > 1
Copy the code

Above we created the function moneyAmount, which returns the current user balance. We use the | | operator to identify without the users account. However, what does that mean when the user doesn’t have an account? It is more accurate to think of no account as empty rather than zero, since bank accounts may have no (or negative) money. In the example above, the | | operator to zero as a false value, should not include user account $0. Let’s use?? Non-airfreight operators to solve this problem:

const currMoney = 0;
const noAccount = null;
function moneyAmount(money) {
  return money ?? 'Account not open';
}
moneyAmount(currMoney); / / = > 0
moneyAmount(noAccount); // => 'The account is not open'
Copy the code

To sum up…? Operator allows us to specify default values while ignoring error values such as 0 and empty strings.

The Optional Chaining operator

? .Also called chain judgment operator. It allows developers to read property values deeply nested in a chain of objects without having to validate each reference. When the reference is null, the expression stops evaluating and returns undefined. Such as:

var travelPlans = {
  destination: "DC".monday: {
    location: "National Mall".budget: 200,}};console.log(travelPlans.tuesday? .location);// => undefined
Copy the code

Now, put together what we’ve just learned

function addPlansWhenUndefined(plans, location, budget) {
  if(plans.tuesday? .location ==undefined) {
    var newPlans = {
      plans,
      tuesday: {
        location: location ?? "Park".budget: budget ?? 200,}}; }else{ newPlans ?? = plans;// Overwrite only if newPlans is undefined
    console.log("Scheduled Plan");
  }
  return newPlans;
}
// The initial value of the travelPlans object, from the example above
var newPlans = addPlansWhenUndefined(travelPlans, "Ford theater".null);
console.log(newPlans);
// => { plans:
// { destination: 'DC',
// Monday: {location: 'National Mall ', budget: 200}},
// Tuesday: {location: 'Ford theatre ', budget: 200}}
newPlans = addPlansWhenUndefined(newPlans, null.null);
// logs => Scheduled
// returns => newPlans object
Copy the code

The example above contains all the operators we have learned so far. We have now created a function that adds the plan to the object Tuesday. Location, which currently has no nested properties.

We also used the non-airfreight operator to provide default values. This function will mistakenly accept a value like “0” as a valid argument. This means that budget can be set to zero without any errors.

const travelPlans = {
  destination: "DC".monday: {
    location: "National Mall".budget: 200,}};/ / bad πŸ‘΄
const res =
  travelPlans &&
  travelPlans.tuesday &&
  travelPlans.tuesday.location &&
  travelPlans.tuesday.location.href;

/ / better πŸ‘Ά
/ / output is undefined
constres1 = travelPlans? .tuesday? .location? .href;Copy the code

BigInt primitive type

Older versions of the JS standard can only have a maximum integer of 2^53– that is, number.max_safe_INTEGER or math.pow (2, 53)

If you can’t accurately calculate numbers greater than 2^53

BigInt is now used to represent integers. There are no restrictions on the number of digits, and any number of digits can be accurately represented.

This is another data type in ECMAScript.

You can define a BigInt by adding n to an integer literal, such as 10n, or by calling the function BigInt().

const theBiggestInt = 9007199254740991n;

const alsoHuge = BigInt(9007199254740991);
/ / β†ͺ 9007199254740991 n
Copy the code
const x = Number.MAX_SAFE_INTEGER;
// β†ͺ 9007199254740991, this is 1 less than 2^53

const y = x + 1;
// β†ͺ 9007199254740992, ok, checks out

const z = x + 2;
// β†ͺ 9007199254740992, wait, that’s the same as above!
Copy the code

As the above example shows, a value greater than number. MAX_SAFE_INTEGER cannot be computed,

This is where you can use BigInt

const previousMaxSafe = BigInt(Number.MAX_SAFE_INTEGER);
/ / β†ͺ 9007199254740991

const maxPlusOne = previousMaxSafe + 1n;
/ / β†ͺ 9007199254740992 n

const theFuture = previousMaxSafe + 2n;
// β†ͺ 9007199254740993n, this works now!

const multi = previousMaxSafe * 2n;
/ / β†ͺ 18014398509481982 n

constSubtr = multi -10n;
/ / β†ͺ 18014398509481972 n

const mod = multi % 10n;
/ / β†ͺ 2 n

const bigN = 2nζ”―ι‚£54n;
/ / β†ͺ 18014398509481984 n

bigN * -1n
N. / / β†ͺ - 18014398509481984
Copy the code
  • Introduction to ES – BigInt

The last

The article is shallow and humble, welcome everyone to see the comment area to leave your opinion!

Feel the harvest of students welcome to like, follow a wave!

The articles

  • The most complete ECMAScript guide
  • ECMAScript ES2015-ES6
  • ECMAScript ES2016-ES7
  • ECMAScript ES2017-ES8
  • ECMAScript ES2018-ES9
  • ECMAScript ES2019-ES10
  • ECMAScript ES2021-ES11
  • ECMAScript ES2020-ES12
  • ECMAScript ES2022-ES13