Express Lane:
ES2021 has been released for some time ECMAScript2021 (ES12) new features, come and review! , have you used the new features of ES2021 yet? Let's take a look at the interesting new features that ES2022 will bring.
This paper will introduce and explain the characteristics of the proposal that has been accepted in the latest draft of the specification.
Each feature proposal follows a process that goes through different stages until stage 4, which indicates that the new features are ready to be included in the formal ECMAScript standard and will be included in the fastest practical standard revision. The following functions have been completed and are in stage 4 and added to ECMAScript in the latest draft.Summary of new features:
- Declare class fields: class fields can be defined and initialized at the top level of the class
- Private methods & fields: private methods and fields of a class are defined with # prefixes
- Static public methods and fields of class: the features of static public fields, static private methods and static private fields are added
- ECMScript class static initialization block: the static initialization code block is evaluated during class declaration / definition, and the private fields of the class can be accessed
- Detect private field: you can use the in operator. If the specified attribute / field is in the specified object / class, it returns true, and you can also judge the private field
- Regular match index: this proposal provides a new / dflag to get additional information about the beginning and end of each match in the input string
- Add. at() method to all built-in indexable data
- Object.hasOwn(object, property): use Object.hasOwn instead of Object.prototype.hasOwnProperty.call
- Error Cause: the cause of the error for convenient transmission
1. Declare the fields of the class
So far, in the ES specification, the field definition and initialization of a class are completed in the constructor of the class. However, in the new proposal, class fields can be defined and initialized at the top level of the classclass Point { name; title; size = 1; }
2. Private methods & fields
use #Prefix to define the private methods and fields of the class.class Person { name; #age; get #age(){ return #age; } $initValue(){ this.name = ''; this.#age = 12; } }
3. Class
Before Field of class and Private method Based on the proposal, the JavaScript class is added Static public fields Static private methods and Properties of static private fields.class Enum { static collectStaticFields() { // Static methods are not enumerable and thus ignored this.enumKeys = Object.keys(this); } } class ColorEnum extends Enum { static red = Symbol('red'); static green = Symbol('green'); static blue = Symbol('blue'); static _ = this.collectStaticFields(); // (A) static logColors() { for (const enumKey of this.enumKeys) { // (B) console.log(enumKey); } } } ColorEnum.logColors(); // Output: // 'red' // 'green' // 'blue'
4. ECMScript class static initialization block
The class static block proposal provides an elegant way to evaluate the static initialization code block during class declaration / definition and access the private fields of the classclass Person { static name; age; } try { Person.name = getNameA(); } catch { Person.name = getNameB(); }
5. Detect private fields
When we try to access a public field that is not declared, we will get undefined results, and an exception will be thrown when accessing a private field. We judge whether there are public fields and private fields according to these two behaviors. However, this proposal introduces a more interesting solution, which includes using the in operator to return true if the specified property / field is in the specified object / class, and can also judge the private fieldclass Person { name; #age; get #age(){ return #age; } $initValue(){ this.name = ''; this.#age = 12; } static hasAge(person){ return #gae in person; } }
6. Regular matching index
The proposal provides a new opportunity /dflag to get additional information about the beginning and end of each match in the input string.const reg = /test(\d)/g; const reg2022 = /test(\d)/dg; const srt = 'test1test2'; const arr = [...str.matchAll(reg)]; const arr2022 = [...str.matchAll(reg2022)]; arr[0] // arr2022[0] //
7. Add. at() method to all built-in indexable data
Add a new array method to get an element through the given index. When the given index is positive, the behavior of this new method is the same as that of access using parentheses, but when we give an index of a negative integer, it works like python's "negative index", which means that the at() method takes a negative integer as the index and counts back from the last item of the group. Therefore, this method can be executed as array.at(-1), and its behavior is the same as that of array[array.length-1], as you can see in the following example.const list = [1,2,3,4,5,6]; console.log(list.at(-1)); // 6 console.log(list.at(-2)); // 5
8,Object.hasOwn(object, property)
To put it simply, use Object.hasOwn instead of Object.prototype.hasOwnProperty.callconst person = {name: 'lxm'} console.log(Object.prototype.hasOwnProperty.call(person, 'name')) // true console.log(Object.hasOwn(person, 'name')) // true
9,Error Cause
proposal-error-cause The purpose of this proposal is to easily transfer the causes of errors. If you do not use this module and want to clearly transfer error context information across multiple call stacks, you usually do this:
async function doJob() { const rawResource = await fetch('//domain/resource-a') .catch(err => { // How to wrap the error properly? // 1. throw new Error('Download raw resource failed: ' + err.message); // 2. const wrapErr = new Error('Download raw resource failed'); // wrapErr.cause = err; // throw wrapErr; // 3. class CustomError extends Error { // constructor(msg, cause) { // super(msg); // this.cause = cause; // } // } // throw new CustomError('Download raw resource failed', err); }) const jobResult = doComputationalHeavyJob(rawResource); await fetch('//domain/upload', { method: 'POST', body: jobResult }); }
await doJob(); // => TypeError: Failed to fetch
According to the syntax of this proposal:
sync function doJob() {
const rawResource = await fetch('//domain/resource-a')
.catch(err => {
throw new Error('Download raw resource failed', { cause: err });
});
const jobResult = doComputationalHeavyJob(rawResource);
await fetch('//domain/upload', { method: 'POST', body: jobResult })
.catch(err => {
throw new Error('Upload job result failed', { cause: err });
});
}
try {
await doJob();
} catch (e) {
console.log(e);
console.log('Caused by', e.cause);
}
// Error: Upload job result failed
// Caused by TypeError: Failed to fetch
Much simpler, this grammar is still very practical!