Владислав Калачев

Что нового в JavaScript ES2020 (ES11) ?

3 095

Доброго времени суток, друзья. На дворе 2К20 год. Окунемся в текущие новшества JavaScript. В этой статье мы рассмотрим следующие темы:

— BigInt

 — Dynamic import

 — GlobalThis

 — Private Class Variables

 — Promise.allSettled()

 — Nullish Coalescing Operator

 — Optional Chaining Operator

 — Numeric Separators

 — String.protype.matchAll

 — import.meta

 — export * as nameModule from «module»

Теперь мы разберем каждую из них более подробно.

BigInt

Начнем наши новшества с чисел. В JavaScript для работы с числами до недавнего времени использовался 64-битный формат IEEE-754, однако данные числа ограничены по длине (2 в степени 53).

Пример:


let num = Number.MAX_SAFE_INTEGER
console.log(num) // 9007199254740991
num + 1 //  9007199254740992
num + 2 //  9007199254740992 ???

BigInt это примитивный тип, который предназначен решить даную проблему. Для того, чтобы получить BigInt можно воспользоваться двумя способами:

1. Передать в число в BigInt конструктор;

2. Дописать n в конце числа;


typeof 99 // ‘number’
typeof 99n // ‘bigint’

Решим выше рассмотренный пример с использованием нового типа:


let bigInt = BigIng(num) + BigIng(2)
console.log(bigInt) // 9007199254740993n

Вот теперь данное вычисление корректно.

Dynamic import

Благодаря динамическим импортам можно более удобно вызывать загрузку модуля в нужном месте в виде промиса.

Пример:


import(‘./module.js’)
  .then(module => {
    //
  })
  .catch(err => {
    //
});

или с использованием async/await

Пример:


(async function() {
	const module = await import(‘./module.js’)
	//
})();

GlobalThis

Часто для доступа к глобальному объекту нужно использовать определенный синтаксис для разных сред исполнения.

— для Node.js это global

— для Worker это self

— для браузера это window, который мы получаем через this.

Раньше, если приложение исполняется в нескольких средах, необходимо было написать дополнительный код с условиями.

Пример:


let global = 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');
};

С нововведением GlobalThis все эти проблемы отошли на второй план:


GlobalThis == this // true

Private Class Variables

После появления в js синтаксического сахара в виде классов некоторые возможности ООП языков не были реализованы, но наступило время приватных полей (модификаторов доступа). Был добавлен символ # (аналог в других языках  private), который позволяет изменить доступ к свойству или методу класса.

Пример:


class User{
	#name = ‘value’
	get name() {
		return this.#name
	}
}

new User().name //  SyntaxError

Так же появились статические свойства.

Пример:


class User{
	static age = 999
}

console.log(User.age) // 999

Promise.allSettled()

Среди ряда уже давно используемых комбинаторов (Promise.all, Promise.race, Promise.any) появился новый allSettled. Promise.allSettled возвращает промис с массивом состояний промисов. Главное условие выполнения данного промиса является выполнение всех исходных промисов, а именно все промисы должны быть завершены, вне зависимости от их статуса.

Пример:


let urls = [
  ‘https://api/test',
  ‘https://api/test2'
];

Promise.allSettled(urls.map(url => fetch(url)))
  .then(results => {
	console.log('Все запросы отработали, можно выполнить действие …’)
});

Nullish Coalescing Operator

При обращение к свойству, значение которого null или undefined, следует получить дефолтное значение. Для такого популярного кейса часто использовался оператор ||, но возникал ряд связанных с ним проблем, для решения которых был добавлен оператор ??

Пример:


let foo = '' || 'string'
console.log(foo) // default string
let foo = ''  ??  'default string';
console.log(foo); // ''
let foo = null ?? 'string';
console.log(foo); // string

Optional Chaining Operator

Данная фича пришла из TypeScript. На мой взгляд, она очень полезна при работе с большой вложенностью у объектов. Часто бывает, что объект имеет несколько уровней вложенности и при обращении к дальнему вложенному ключу, может произойти ошибка из-за его отсутствия. В качестве решения создавалась условная проверка для каждого такого свойства. Оператор опциональных цепочек (?) позволяет легко решить эту задачу без написания лишнего кода.

Пример:


const obj = { body: { a: 1, b: 2 } }
// old
const value = obj.body && obj.body.a
// new
const value = obj.body?.a

Numeric Separators 

Еще со времен написания кода на Java, C# меня раздражало, что в js из-за отсутствия разделителей, нет возможности более ясно визуализировать большие числа. Во многих языках эту роль играют сепараторы, вот и настало время этой фичи в js.

Давайте напишем такое условие с использованием числового сепаратора: 50000 == 50_000 // true. Помните, что это просто синтаксический сахар и выражение: 50000 == 50_0_0_0 // true

также истинно. Это фича только для вашего визуального восприятия, она не является технической и не несет какой-либо функциональности.

String.protype.matchAll

MatchAll — метод объекта string, позволяющий получить итератор при совпадении регулярного выражения со строкой. Главная его фишка это получение в массиве индексов с текущими совпадениями. Старый метод match, выполняющий аналогичную работу, возвращает лишь массив найденных значений (при условии добавления в регулярку g ).

Пример:


let reg = /value (\d+)/g;
let str = 'value 2 value 10';
console.log(str.match(reg));
// ["value 2", "value 10"]
let matches;
while ((matches = reg.exec(str)) !== null) {
  console.log(matches);
}
// ["value 2", "2", index: 0, input: "value 2 value 10", groups: undefined]
// ["value 10", "10", index: 8, input: "value 2 value 10", groups: undefined]

import.meta

Для работы с метаданными модулей появился объект import.meta.

Пример получения мета данных файла .jpg:


const res = await fetch(new URL("./image.jpg", import.meta.url));
const blob = await res.blob();
const size = import.meta.scriptElement.dataset.size || 300;

Еще пример:


<script type="module" src="module.js"></script>

console.log(import.meta); // { url: "file:///app/module.js" }

Мы загружаем .js модуль через тег script и в результате в исполняемом файле получаем метаданные модуля. К слову, до появления import.meta использовались библиотеки, но речь в данной статье не о них.

export *

Напоследок еще одна новая фича — экспорт всего содержимого из модуля. По сути export * аналогичен импорту всего модуля в обратном направлении.

Пример:


import * as moduleName from "module"
export * as nameModule from "module"

Такая запись дает удобство и экономию в написании кода.

Заключение

Надеюсь данная статья была вам полезна. Мы рассмотрели основные новшества, которые будут нас радовать в ES11. Все эти нововведения в первую очередь дают нам более удобный лаконичный синтаксис для решения наших повседневных задач. Меньше кода — выше эффективность. Учитесь, думайте, пишите код. Удачного кодинга, друзья!

Полезные ссылки:

https://tc39.es/ecma262 — спецификация ECMA-262

Подписывайтесь на наш канал в Telegram и на YouTube для получения самой последней и актуальной информации. 

Комментарии:

Что нового в JavaScript ES2020 (ES11) ?: 1 комментарий

  1. Отлично. И кто же Вам мешает её использовать? Уверяю, ни одно нововведение в движке старый код не порушит. Более того, даже если новый код будет написан с использованием нововведений, он сможет использоваться совместно со старым.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *