41

8 New Features Shipping With ES2020 - Better Programming - Medium

 4 years ago
source link: https://medium.com/better-programming/8-new-features-shipping-with-es2020-7a2721f710fb
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

7 New Features Shipping With ES2020

GlobalThis, optional chaining, private fields in classes, the nullish coalescing operator, and more

Image for post
Image for post
Photo by Tomasz Frankowski on Unsplash

As you might know, since ES6 in 2015, a new version of ECMAScript is released each year, by Ecma International’s TC39. ECMAScript 2020 is the 11th edition of the ECMAScript Language Specification.

This new iteration comes with its own batch of new features — let’s review them!

1. ‘globalThis’

The JavaScript language is quite popular now and can be used in a wide variety of environments — in web browsers, of course, but JavaScript can also be run server-side, on smartphones, robotically, etc.

Each environment comes with its own object model and syntax to access the global object. Because of that, it can be tough to write JavaScript code that works in multiple environments:

// browser environment
console.log(window);

// node.js environment
console.log(global);

// Service worker environment
console.log(self);// ...

It is, of course, possible to standardize it across multiple platforms by writing a function that checks for the current environment, but this won’t be needed anymore!

The globalThis property is now the standard way of accessing the global object — across environments — in a consistent manner.

2. ‘Promise.allSettled()’

The Promise.allSettled() method returns a promise that resolves after all of the given promises have either resolved or been rejected, with an array of objects that each describe the outcome of each promise via the status property. This makes it easier to filter them.

const p1 = new Promise((res) => res("🍕"));
const p2 = new Promise((res, rej) => rej("🍍"));
const p3 = new Promise((res) => res("🍺"));Promise.allSettled([p1, p2, p3]).then(data => console.log(data));
// [
// { status: "fulfilled", value: "🍕" },
// { status: "rejected", value: "🍍" },
// { status: "fulfilled", value: "🍺" },
// ]

3. The Nullish Coalescing Operator

The nullish coalescing operator is a new tool in your toolbox when trying to provide a default value when performing property accesses. It differs from the or operator, symbolized with || between two values, in the manner that it treats nullary values.

Let’s see it in action by comparing the two operators:

const test = {
null: null,
number: 0,
string: '',
boolean: false
};const undefinedValue = test.dog || "Cat"; // "Cat"
const undefinedValue = test.dog ?? "Cat"; // "Cat"const nullValue = test.null || "Default"; // "Default"
const nullValue2 = test.null ?? "Default"; // "Default"const numberValue = test.number || 1; // 1
const numberValue2 = test.number ?? 1; // 0const stringValue = test.string || "Hello"; // "Hello"
const stringValue2 = test.string ?? "Hello"; // ""const booleanValue = test.boolean || true; // true
const booleanValue2 = test.boolean ?? true; // false

As you can see, the nullish coalsceing operator only picks the right-hand side value if and only if the expression at the left-hand side of the ?? is either null or undefined.

4. The Optional Chaining Operator

Until now, when looking for a property value that’s deeply nested inside an object or using an API that returns either an object or null/undefined, one often has to proceed this way to check for intermediate values:

// Checking for intermediate nodes:
const deeplyNestedValue = obj && obj.prop1 && obj.prop1.prop2;// Checking if the node exists in the DOM:
const fooInputEl = document.querySelector('input[name=foo]');
const fooValue = fooInputEl && fooInputEl.value;

The optional chaining operator allows us to handle many of those cases in a handier way. Rewriting the examples above would give:

// Checking for intermediate nodes:
const deeplyNestedValue = obj?.prop1?.prop2;// Checking if the node exists in the DOM:
const fooValue = document.querySelector('input[name=foo]')?.value;

Good to know

The optional chaining operator is short-circuiting, which means it stops to evaluate the line if the left-hand side of ?. evaluates to null or undefined:

// x is incremented if and only if 'a' is not null or undefined
a?.[++x]

Last thing: The optional chaining operator also works with functions.

func?.(...args) // optional function or method call

5. ‘BigInt’

We already have Number to represent numbers in JavaScript. Problem is, the biggest number is 2⁵³. Above that, it’s not really reliable anymore.

const x = Number.MAX_SAFE_INTEGER; // 9007199254740991
const y = x + 1; // 9007199254740992 • equal to 2^53
const z = x + 2; // 9007199254740992 • well, it's broken

You got it: BigInt is a new primitive to provide a way to represent a number larger than 2 ⁵³. It’s created by appending an n to the end of an integer:

const aBigInteger = 9007199254740993n;
// There is also a constructor:
const evenBigger = BigInt(9007199254740994); // 9007199254740994n
const fromString = BigInt("9007199254740995"); // 9007199254740995n

Good to know

A BigInt mostly has the same behavior as a number, but they can’t be used together in an operation:

let sum = 1n + 2, multiplication = 1n * 2;
// TypeError: Cannot mix BigInt and other types, use explicit conversions

A BigInt can be converted to a Number using the constructor Number(), but in certain cases, you might be losing the precision. For this reason, it’s recommended to only use BigInt when large values are expected in your code.

Number(900719925474099267n); // 900719925474099300 • 🤷‍♂️

6. ‘dynamic import()’

The current form of importing modules import module from './module' is static and only accepts a string literal. It also only works at preruntime as a linking process.

The dynamic import(...) allows developers to be able to dynamically load parts of a JavaScript application at runtime. This comes with multiple advantages the current import doesn’t support:

  • Load user’s language instead of loading them all
  • Lazy loading of routes of your application (improving performance)
  • Can handle failure if the module isn’t found

How does it work?

// Used as a function, import() returns a promise that can be handled the 2 usuals ways:// Using callback
import(
'/module.js')
.then((module) => {
// Do something with the module.
});// Using async / await
async function () {
let module = await import('/modules.js');
}

Here are the notable differences, compared to the usual import declaration:

  • import() can be used from scripts, not just from modules
  • import() can occur anywhere at any level, and isn’t hoisted
  • import() accepts arbitrary strings (with runtime-determined template strings, as shown here), not just static string literals

7. ‘String.protype.matchAll’

The matchAll() method returns an iterator of all the results matching a string against a regular expression (RegExp) and work this way:

const regexp = RegExp('[a-z]*ball','g');
const str = 'basketball handball pingpong football';
const matches = str.matchAll(regexp);// Since it is an iterator, you can loop trought results this way:
let match = matches.next();
while (!match.done) {
console.log(match.value);
match = matches.next();
}
// ["basketball", index: 0, input: "basketb...", groups: undefined]
// ["handball", index: 11, input: "basketb...", groups: undefined]
// ["football", index: 29, input: "basketb...", groups: undefined]// One can also get an array of all results
let results = [...str.matchAll(regexp)];

Good to know

While the match() method doesn’t return capture groups when used with the global /g flag, matchAll() does.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK