preface

Ecma International

Ecma International is an International membership system of information and telecommunications standards organization, it is closely linked with the organization of enterprises, so Ecma International standards are mainly formulated and promoted by various enterprises. Ecma-262 is a scripting language standard developed by TC39 group under THE organization of ECMA.

TC39

TC39 is part of Ecma International, a group of JavaScript developers, implementers, academics, and others who work with the JavaScript community to maintain and develop the JavaScript standard. Partial membership of TC39 Committee

TC39 proposal process

Each ECMAScript proposal will go through the following phases, starting with Stage 0, and progress from one phase to the next must be approved by TC39:

  1. Stage-0: Again an idea that can only be proposed by TC39 members or TC39 contributors;
  2. Stag-1: A formal proposal can only be initiated by TC39 members and the problem to be addressed must be formally described in writing.
  3. Stage-2: draft, with an initial specification, a formal description of functional syntax and semantics, including some experimental implementations;
  4. Stage-3: candidate. The proposal has been basically implemented and needs to wait for experimental verification, user feedback and acceptance test.
  5. Stage-4: Completed and must pass the Test262 acceptance test before being incorporated into the ECMA standard.

ECMA-262

The ECMA-262 standard defines the ECMAscript language specification. This standard is also known as the ECMAscript Language Specification, or ES Specification for short. In 1997, ECMA published the McMa-262 standard, which sets the MCMAscript language specification. Based on this language specification, THE TC39 Committee formulated ECMAscript specification and officially published it that year, marking the birth of ES specification. The ES specification has had eleven versions since its release in 1997. ECMAscript is based on several primitive technologies, most notably javascript (Netscape Navigator 2.0), JScript (Microsoft IE3), and ECMA-262 Version 6, also known as ES6 (or ES2015).

ECMAScript and JavaScript

According to the above analysis, the following conclusions can be drawn:

  • Ecma-262 is a technical standard published by ECMA International.
  • In ECMA-262, the specification is defined for the programming language ECMAScript.
  • JavaScript is a programming language that follows the ECMAScript programming language specification.

So ES5, ES6, ES7… What is it? A: They are version numbers of the ECMA-262 standard. In 2015 ECMA International decided to release an annual version of ECMAScript, so ES6 was renamed ES2015 to reflect the year of release, so ES6 and ES2015 mean the same thing! The subsequent annual releases are called ES2016 (ES7), ES2017 (ES8), and ES2018 (ES9).

ES2020

globalThis

GlobalThis — The generic top-level object that points to this in any context.

before

  • Browser: The top-level object is window;
  • Node: The top-level object is global;
  • WebWorker: The top-level object is self.

now

Use the generic top-level object: globalThis. In all three environments, you can use globalThis directly to get globalThis. Therefore, globalThis aims to provide a standardized way to access global objects, and with globalThis you can get global objects in any context at any time. GlobalThis will be Window if you are on a browser, and global if you are on Node. As a result, there is no longer a need to consider different environmental issues. GlobalThis is a new standard method for retrieving globalThis.

// Mount a 'v' attribute to the global object with the value 'true' :
// Pre-ES11 solution
const getGlobal = function () {
  if (typeofself ! = ="undefined") {
    return self;
  }
  if (typeof window! = ="undefined") {
    return window;
  }
  if (typeof global! = ="undefined") {
    return global;
  }
  throw new Error("unable to locate global object");
};
getGlobal().v = true;
console.log(getGlobal().v); // true

// ES11 is defined as follows
globalThis.v1 = true;
console.log(globalThis.v1); // true
Copy the code

BigInt

BigInt — An arbitrary number of digits (new data type, ending with n). In javascript integer operation, only when the calculated value and the result value are in the range of number. MIN_SAFE_INTEGER to number. MAX_SAFE_INTEGER can ensure the correct operation result. So ES11 adds BigInt as a seventh primitive data type for calculating large integer operations exactly.

Some BigInt methods

  • BigInt() : Converts a common value to BigInt;
  • Bigint.parseint () : Similar to number.parseint (), converts a string to a specified base BigInt type.

Pay attention to the point;

  • BigInt can also be represented in a variety of bases, all suffixed;
  • BigInt and Number are two kinds of values. They are not congruent and can be compared but cannot be calculated.
  • Typeof operator returns BigInt for data of type BigInt.
let bigintA = BigInt(Number.MAX_SAFE_INTEGER);
let intB = Number.MAX_SAFE_INTEGER;
console.log(bigintA); // 9007199254740991n
console.log(bigintA == intB);// true
console.log(bigintA === intB);// false
console.log(bigintA * 2n); // 18014398509481982n
Copy the code

The optional chain operator (? .).

The optional chain operator (? .). When we want to find multi-level objects, we need to carry out redundant pre-check for attribute protection, otherwise it is easy to report errors and cause the program to stop running. Using the chain judgment operator in ES11 can greatly simplify this pre-validation:

const user = {
  info: {
    name: "hahahh",}};// Before es11
let name1 = user && user.info && user.info.name;
// after es11
letname2 = user? .info?.name;console.log(name1); // hahahh
console.log(name2); // hahahh

user.info = null; name1 = user && user.info && user.info.name; name2 = user? .info?.name;console.log(name1); // null
console.log(name2); // undefined
Copy the code

Null-value merge operator (??)

Null-value merge operator (??) Is a logical operator that returns the right-hand operand if the left-hand operand is null or undefined, otherwise returns the left-hand operand. When we query an attribute, we often set a default value without the attribute, such as the following two ways:

let a = 0,
  b = true;
let c = a ? a : b; // Mode 1- ternary operator
let d = a || b; / / way 2 - logical operators | |

console.log(c);// true
console.log(d);// true
Copy the code

The above two methods, however, have an obvious drawback. They overwrite all false values (0, “, false), because the left-hand operand is cast to a Boolean value for evaluation, and these values may be valid in some cases. This problem can be avoided by using the void merge operator. It returns the value of the expression or variable to its right only if the first operand is undefined or null.

let a = 0,
  b = true;
let c = a ? a : b; // Mode 1- ternary operator
let d = a || b; / / way 2 - logical operators | |
console.log(c); // true
console.log(d); // true

let e = a ?? b 
console.log(e); / / 0
Copy the code

Import () Dynamic import

Import is a new directive introduced in ES6 and is the basis of the ESM specification. Modern front-end has more and more packaged resources, and the more resources introduced, the slower the loading speed of the first screen will be. However, front-end application initialization does not require a full load of logical resources. In order to speed up the rendering of the first screen, these modules can be imported on demand. Previously, we would split the JS module through webpack and load it with asynchronous import (the principle is to re-issue a GET request to get the JS script). The appearance of the import() directive further standardizes this asynchronous loading capability!

usage

The keyword import can be used to dynamically import modules as if they were functions. Called this way, a Promise is returned. By default, the imported module is mounted under the default property of the Promise object.

<! DOCTYPEhtml>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
    <title>dynamic-import</title>
  </head>
  <body>
    <script>
      function handleClick() {
        import("./module.js")
          .then((module) = > {
            console.log(module.default());
          })
          .catch((err) = > {
            console.error("error~");
          });
      }
    </script>
    <button onclick="handleClick()">According to the need to load</button>
  </body>
</html>
Copy the code

Of course, the async-await syntactic sugar can be used to parse the promise object returned by import() :

<script>
  async function handleClick() {
    const fn = await import("./module.js");
    fn.default();
  }
</script>
Copy the code

The characteristics of

Compared to import declarations, import() has the following characteristics:

  • Can be used in functions, branches and other non-top-level scope, loading on demand, lazy loading is not a problem;
  • Module identification supports variable input and can be dynamically calculated to determine the module identification.
  • It is not limited to modules, but can be used in plain script.

Note: Although it looks like a function, import() is actually an operator, because operators can carry information about the current module (used to parse module representations), whereas functions cannot.

Applicable scenario

  1. Load on demand (such as loading a file or module when clicked);
  2. Conditional loading (such as in the if judgment module);
  3. Dynamic module paths (e.g. module paths are generated in real time).

Dynamic import() is useful when you want to load modules under certain conditions or on demand. While static imports are the best choice for initializing load dependencies, using static imports is easier to benefit from code static analysis tools and tree shaking.

For-in traversal order

The for-in operator is typically used to iterate over an object’s key. The traversal operation inevitably involves the traversal order, and the traversal order of for-In is somewhat different from browser vendors. Es11 regulates this, ensuring that traversal results are consistent across browser engines!

The rules

For example, the integer attributes are iterated first, and the key of the object is iterated in ascending order, then the other attributes are iterated in the order they were created:

const obj = {
  x2: "x2".x1: "x1".3: "3".1: "1".2: "2"."3xx": "3xx"};for (let key in obj) {
  console.log(key); // 1 2 3 x2 x1 3xx
}
Copy the code

supplement

For-in traversal object

  • Attribute of type Symbol cannot be traversed;
  • In the traversal process, the attributes of the target object can be deleted, ignoring the attributes that have not been traversed but have been deleted.
  • If a new attribute is added during traversal, it is not guaranteed that the new attribute can be processed by the next traversal.
  • Property names do not appear twice (a property name appears at most once);
  • Properties in the entire prototype chain of the target object can be traversed.

String.prototype.matchAll

A common scenario for string processing is to want to match all the target substrings in a string and then output or replace them. Es11 added a new prototype method to String objects: matchAll, which can fetch all matches at once. Grammar:

str.matchAll(regexp)
Copy the code
  • Parameter: regEXP Regular expression object. If the passed parameter is not a regular expression object, it is implicitly converted to a RegExp using new RegExp(obj).
  • Returns an iterator (not reusable, the result is exhausted and the method needs to be called again to get a new iterator).
  • Note that RegExp must be set to global mode G, otherwise TypeError will be raised.

Difference between matchAll() and match(

  • matchAll()Matches all matching strings without using a re (if you use a re, you cannot use a re without the G modifier, otherwise an error will be reported);
  • match()The regular expression with g is used to match all of them. Otherwise, only the first one is matched.
  • When there are multiple matchesmatchAll()Don’t likematch()Returns an iterator that can be used instead of an arrayfor-ofTraversal, array extension (...) results orArray.from()Convert to an array.
const str = "< text > javascript < / text > < text > regular < / text >";
const matchStr = str.match(/
      
       (.*?) <\/text>/
      );
const allMatchs = str.matchAll(/
      
       (.*?) <\/text>/g
      );
console.log(matchStr[0]);
console.log(allMatchs);
for (const match of allMatchs) {
  console.log(match[0]);
}
Copy the code

Results:

Promise.allSettled()

The promise.allSettled () method returns a Promise after all the given promises have fulfilled or rejected, with an array of objects each representing the corresponding Promise result. It is often used when multiple asynchronous tasks have successfully completed independently of each other, or when you always want to know the outcome of each promise. Promise.all(), by contrast, is better suited to relying on each other or ending immediately in either reject. Example :(implement a filter to filter out the rejected state Promise)

async function fulfilled() {
  return Promise.allSettled([
    Promise.reject({ code: 500.msg: "Abnormal service" }),
    Promise.resolve({ code: 200.list: []}),Promise.resolve({ code: 200.list: [] }),
  ]).then((res) = > {
    console.log("all = ", res);
    // Filter out the Rejected state
    return new Promise((resolve) = > {
      resolve(
        res.filter((el) = > {
          returnel.status ! = ="rejected"; })); }); }); } fulfilled().then((res) = > {
  console.log("fulfilled = ", res);
});

Copy the code

Results:

ES2021

WeakRef

A WeakRef object allows a weak reference to another object to be preserved without preventing the weakly referenced object from being reclaimed by GC.

describe

A WeakRef object contains a weak reference to the object, which is called the target or referent of the WeakRef object. A weak reference to an object means that it does not prevent the GC from collecting when the object should be collected by the GC. In contrast, a normal reference (strong by default) keeps its corresponding object in memory. Only if the object does not have any strong references does the JavaScript engine GC destroy the object and reclaim the memory occupied by the object. If that happens, then you can’t get the object through any weak references. Such as storing DOM nodes without worrying about memory leaks when they are removed. You must use the new keyword to create a new WeakRef and put the object in parentheses as an argument. When you want to read a referenced object, you can do this by calling deref() on a weakly referenced object. Here is a very simple example:

let obj = {
  name: "Cache".size: "unlimited"};const myWeakRef = new WeakRef(obj);

console.log(myWeakRef.deref());
console.log(myWeakRef.deref().name);
console.log(myWeakRef.deref().size);
Copy the code

Results:

FinalizationRegistry

The FinalizationRegistry object allows you to request a callback when the object is garbage collected. FinalizationRegistry provides a way to execute the finalizer callback method that the object owns when an object registered in the registry is reclaimed, that is, to perform a cleanup callback (sometimes called finalizer).

Method of use

  • createregistry:
const registry = new FinalizationRegistry(heldValue= > {
  / /...
});
Copy the code
  • callregisterMethod to register any object you want to clean up the callback, pass in that object andContains the value:
registry.register(theObject, "some value");
Copy the code
  • When you need to undo the cleanup callback on theObject:
registry.unregister(theObject);
Copy the code

A simple example

const a = {};
const obj = new WeakRef(a);
const fina = new FinalizationRegistry((v) = > {
  console.log(v);
});

fina.register(a, "A was recycled.");
console.log(a); / / {}

/**** Suppose at the moment a is recycled ****/

// First print: A is recycled
console.log(obj.deref()); // undefined
Copy the code

String.prototype.replaceAll()

The replaceAll() method returns a new string, all parts of which meet pattern are replaced by replacement. Pattern can be a string or a RegExp, replacement can be a string or a function that is called each time a match is made.

grammar

const newStr = str.replaceAll(regexp|substr, newSubstr|function)
Copy the code

Note: When using a Regex, you must set the global (” G “) flag, otherwise, it will raise TypeError: “replaceAll must be called with a global RegExp”.

The sample

let str = "a+b+c";
let s1 = str.replace(/\+/g."");
let s2 = str.split("+").join("");
let s3 = str.replaceAll("+"."");

console.log(s1);
console.log(s2);
console.log(s3);
Copy the code

Results:

The logical assignment operator

Logic assignment operator combines the logic operations (&&, | | or??) And the assignment operator. We know the following code:

let a = 0;
a = a + 2;
Copy the code

This can be abbreviated as:

let a = 0;
a += 2;
Copy the code

ES2021 lieutenant general logical operators | |, &&,?????? And = operator, | | =, && =?? = three logical assignment operators:

let a = true,
  b = false,
  c;
a ||= b; / / is equivalent to a = a | | b, true

a &&= b; // a = a &&b, falsec ?? = b;// same as c = c?? B, false
Copy the code

Promise.any()

Promise.any() takes a Promise iterable (array, Set, Map) and returns the successful Promise if one of the promises succeeds. If none of the promises in the iterable succeed (i.e. all Promises fail/reject), return an instance of the failed promise and AggregateError type, which is a subclass of Error and is used to group single errors together. This method can be thought of as the reverse of promise.all (). A simple example:

const promise1 = new Promise((resolve, reject) = > {
  console.log("promise1 done!");
  reject("I promise1 fails");
});

const promise2 = new Promise((resolve, reject) = > {
  console.log("promise2 done!");
  setTimeout(resolve, 500."My promise2 succeeds.");
});

const promise3 = new Promise((resolve, reject) = > {
  console.log("promise3 done!");
  setTimeout(resolve, 100."My Promise3 is successful");
});

Promise.any([promise1, promise2, promise3]).then((value) = > {
  console.log("promise.any = ", value);
});

Copy the code

Results:

If there is no successful promise, promise.any () returns AggregateError:


const promise1 = new Promise((resolve, reject) = > {
  console.log("promise1 done!");
  reject("I promise1 fails");
});

const promise2 = new Promise((resolve, reject) = > {
  console.log("promise2 done!");
  reject("My promise2 fails");
});

const promise3 = new Promise((resolve, reject) = > {
  console.log("promise3 done!");
  reject("My promise3 fails");
});

Promise.any([promise1, promise2, promise3]).then((value) = > {
  console.log(value);
});


Copy the code

Results:

Numeric separator

With this feature, we use the “(_ [U+005F])” separator to group numbers and improve the readability of numbers:

let x = 233 _333_333;
// the x value is the same as 233333333, only this is more readable
console.log(x);
Copy the code

Intl.ListFormat

Intl.ListFormat is a language-specific list formatting constructor. Grammar:

new Intl.ListFormat([locales[, options]])
Copy the code

The constructor of the ListFormat object takes two optional arguments.

Locales: a string or an array of strings that conform to the BCP 47 notation. Possible values include en, zh-hans-cn, it, de, and so on. Options: The second argument is an option object containing the localeMatcher, style, and Type attributes.

Example:

const arr = ["Pen"."Pencil"."Paper"];

let obj = new Intl.ListFormat("en", { style: "short".type: "conjunction" });
console.log(obj.format(arr)); // Pen, Pencil, & Paper

obj = new Intl.ListFormat("zh-Hans-CN", {
  style: "short".type: "conjunction"});console.log(obj.format(arr)); // Pen, Pencil, Paper

obj = new Intl.ListFormat("en", { style: "long".type: "conjunction" });
console.log(obj.format(arr)); // Pen, Pencil, and Paper

obj = new Intl.ListFormat("en", { style: "narrow".type: "conjunction" });
console.log(obj.format(arr)); // Pen, Pencil, Paper

// Pass in the Italian logo
obj = new Intl.ListFormat("it", { style: "short".type: "conjunction" });
console.log(obj.format(arr)); // Pen, Pencil e Paper

// Pass in the German flag
obj = new Intl.ListFormat("de", { style: "long".type: "conjunction" });
console.log(obj.format(arr)); // Pen, Pencil e Paper

Copy the code

Results: