GlobalThis, необязательное связывание, частные поля в классах, нулевой оператор объединения и многое другое.
Как вы, возможно, знаете, начиная с ES6 в 2015 году, каждый год TC39 из Ecma International выпускает новую версию ECMAScript. ECMAScript 2020 - это 11-е издание спецификации языка ECMAScript.
Эта новая итерация включает в себя ряд новых функций - давайте рассмотрим их!
1. «globalThis»
Язык JavaScript сейчас довольно популярен и может использоваться в самых разных средах - в веб-браузерах, конечно, но JavaScript также можно запускать на стороне сервера, на смартфонах, роботизированно и т. Д.
Каждая среда имеет собственную объектную модель и синтаксис для доступа к глобальному объекту. Из-за этого может быть сложно написать код JavaScript, который работает в нескольких средах:
// browser environment console.log(window); // node.js environment console.log(global); // Service worker environment console.log(self); // ...
Конечно, можно стандартизировать его для нескольких платформ, написав функцию, которая проверяет текущую среду, но это больше не понадобится!
Свойство globalThis
теперь является стандартным способом согласованного доступа к глобальному объекту в разных средах.
2. «Promise.allSettled ()»
Метод Promise.allSettled()
возвращает обещание, которое разрешается после того, как все данные обещания были разрешены или отклонены, с массивом объектов, каждый из которых описывает результат каждого обещания через свойство status. Это упрощает их фильтрацию.
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. Оператор нулевого слияния
Оператор объединения с нулевым значением - это новый инструмент в вашем наборе инструментов, когда вы пытаетесь предоставить значение по умолчанию при выполнении доступа к свойствам. Он отличается от оператора или, обозначенного знаком ||
между двумя значениями, тем, как он обрабатывает нулевые значения.
Давайте посмотрим, как это работает, сравнив два оператора:
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; // 0 const stringValue = test.string || "Hello"; // "Hello" const stringValue2 = test.string ?? "Hello"; // "" const booleanValue = test.boolean || true; // true const booleanValue2 = test.boolean ?? true; // false
Как видите, нулевой оператор coalsceing выбирает значение в правой части только тогда, когда выражение в левой части ??
равно null
или undefined
.
4. Необязательный оператор цепочки
До сих пор при поиске значения свойства, которое глубоко вложено в объект, или при использовании API, возвращающего либо объект, либо null / undefined, часто приходилось действовать следующим образом для проверки промежуточных значений:
// 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;
Необязательный оператор цепочки позволяет нам обрабатывать многие из этих случаев более удобным способом. Переписывание приведенных выше примеров даст:
// 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;
Полезно знать
Необязательный оператор цепочки - это короткое замыкание, что означает, что он прекращает оценку строки, если левая часть ?.
оценивается как null или undefined:
// x is incremented if and only if 'a' is not null or undefined a?.[++x]
И последнее: необязательный оператор цепочки также работает с функциями.
func?.(...args) // optional function or method call
5. «BigInt»
У нас уже есть Number
для представления чисел в JavaScript. Проблема в том, что наибольшее число 2⁵³. Кроме того, это уже не совсем надежно.
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
Вы поняли: BigInt
- это новый примитив, обеспечивающий способ представления числа больше 2 ⁵³. Он создается добавлением n
в конец целого числа:
const aBigInteger = 9007199254740993n; // There is also a constructor: const evenBigger = BigInt(9007199254740994); // 9007199254740994n const fromString = BigInt("9007199254740995"); // 9007199254740995n
Полезно знать
BigInt
в основном ведет себя так же, как number
, но их нельзя использовать вместе в операции:
let sum = 1n + 2, multiplication = 1n * 2; // TypeError: Cannot mix BigInt and other types, use explicit conversions
BigInt
можно преобразовать в Number
с помощью конструктора Number()
, но в некоторых случаях вы можете потерять точность. По этой причине рекомендуется использовать BigInt
только тогда, когда в вашем коде ожидаются большие значения.
Number(900719925474099267n); // 900719925474099300 • 🤷♂️
6. «динамический импорт ()»
Текущая форма импорта модулей import module from './module'
является статической и принимает только строковый литерал. Он также работает только перед запуском как процесс связывания.
Динамический import(...)
позволяет разработчикам динамически загружать части приложения JavaScript во время выполнения. Это дает несколько преимуществ, которые сейчас import
не поддерживает:
- Загружать язык пользователя вместо того, чтобы загружать их все
- Ленивая загрузка маршрутов вашего приложения (повышение производительности)
- Может справиться с ошибкой, если модуль не найден
Как это работает?
// 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 / awaitasync function () { let module = await import('/modules.js'); }
Вот заметные отличия от обычного объявления import
:
import()
можно использовать из скриптов, а не только из модулейimport()
может произойти где угодно на любом уровне и не поднимаетсяimport()
принимает произвольные строки (с определенными во время выполнения шаблонными строками, как показано здесь), а не только статические строковые литералы.
7. «String.protype.matchAll»
Метод matchAll()
возвращает итератор всех результатов, соответствующих строке и регулярному выражению (RegExp
), и работает следующим образом:
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)];
Полезно знать
Хотя метод match()
не возвращает группы захвата при использовании с глобальным флагом /g
, matchAll()
это делает.
Заключение
На этот год все!
В Babel уже есть плагины почти для всех этих функций. Если вам не терпится использовать их в своих проектах, вот ссылки:
- @ Babel / плагин-предложение-нулевой-коалесцирующий-оператор
- @ Babel / плагин-предложение-частные-методы
- @ Babel / плагин-предложение-необязательная-цепочка
- @ Babel / плагин-синтаксис-bigint
- @ Babel / плагин-синтаксис-динамический-импорт
Спасибо за прочтение!