8 новых функций JavaScript, которые вы могли пропустить

автор vadim


Джаггернаут JavaScript никогда не останавливается. Ежегодно в «живую спецификацию» вводится ряд функций. Затем браузерам, Node.js и т. д. требуется некоторое время, чтобы их внедрить, и прежде чем вы это заметите, появится большая куча новых функций JavaScript, которые вы еще не пробовали.

Еще не поздно. Здесь я собрал функции ES11 (ECMAScript 11, также известный как ECMAScript 2020), которые вы, возможно, пропустили. Они включают в себя ряд эргономических и других современных усовершенствований. Давайте взглянем.

Дополнительное связывание

Дополнительная цепочка — одна из тех простых, но эффективных тонкостей, которая делает жизнь немного проще. Эта функция позволяет перемещаться по цепочкам объектов и функций с помощью сокращений для работы с нулевыми или неопределенными значениями.

Необязательная цепочка работает для простых случаев, таких как данные вложенных объектов, для функций, которые возвращают несуществующие значения, и даже для функций, которые не существуют в качестве методов-членов объектов. Таким образом, вы можете делать то, что мы видим в листинге 1.

Листинг 1. Примеры дополнительных цепочек

box = {
  innerBox: {},
  nullFunction: function() { return null; },
  // non-existent method foo() and members bar
}
// with optional chaining:
if (box?.innerBox?.foo){ }// navigate object graph safely
// old style without optional chaining:
if (box.innerBox && box.innerBox.foo){ }
//also works for functions:
box.nullFunction()?.foo
// and nonexistent methods and members:
box?.foo() && box?.bar

Код более лаконично выражает то, что вы хотите: если вещь существует, перейдите к ней; если нет, верните неопределенное.

globalThis

Еще одно разумное дополнение к основному языку, globalThis, представляет собой абстракцию глобального объекта, доступного текущему контексту. Самым известным и древним из них является объект window, который можно найти в JavaScript, работающем в браузере. Но такие среды, как Node.js и веб-воркеры, имеют свои собственные корневые объекты, которые служат одной и той же цели: глобальные и собственные соответственно.

globalThis делает код более переносимым (и устраняет проверки существования), заключая все эти корневые объекты в один идентификатор, который разрешается в глобальный корневой объект в любой среде, в которой выполняется код.

БигИнт

До ES11 самым большим целым числом, на которое можно было безопасно ссылаться в JavaScript, было Number.MAX_SAFE_INTEGER, которое разрешалось в 9007199254740991 (также известное как 2^53 – 1). Возможно, для некоторых из нас это не является повседневной проблемой, но для многих приложений это забавно маленькая величина, требующая от программистов использования оболочки типа big-integer. (Обратите внимание, что библиотека больших целых чисел по-прежнему полезна в качестве полифилла.)

При использовании традиционного числового типа для представления таких больших чисел вы можете столкнуться с неожиданным округлением. (Обратите внимание, что все эти комментарии относятся к очень маленький числа, т.е. -2^53 – 1).

В ES11 для этих сценариев встроен тип BigInt. Вы можете определить это, добавив n в конец числа, как в mySafeBigNumber = 9007199254740992n.

Это действительно новый тип, а не просто какой-то трюк с существующим числовым типом. Если ты это сделаешь typeof 12Вы получаете number. Если ты это сделаешь typeof mySafeBigNumberВы получаете bigint. Более того, если вы попробуете что-нибудь гнусное, например mySafeBigNumber - 12вы получите сообщение об ошибке: «Невозможно смешивать BigInt и другие типы, используйте явные преобразования».

Для преобразования между ними вы можете использовать конструкторы. Например, вы можете написать let myUnsfeBigNumber = Number(mySafeBigNumber), но подождите — вам не следует этого делать, поскольку вы только что создали небезопасно большой объект Number. Поэтому вместо этого конвертируйте только тогда, когда BigInt уменьшен до значения меньше значения MAX_SAFE_INTEGER.

Аналогичным образом стоит отметить, что сравнение чисел и BigInts на предмет равенства всегда будет возвращать значение false, поскольку они относятся к разным типам.

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

Наконец, может показаться излишним указывать, поскольку это указано в самом названии, но BigInt представляет собой целые числа. Запуск кода x = 3n; x = x / 2n; приведет к значению 1n для x. BigInts спокойно избавляется от дробной части чисел.

Нулевое слияние

Нулевое объединение — это наиболее поэтично названная из функций ES11, которая присоединяется к опциональной цепочке, помогая нам работать с нулевыми значениями. Нулевое слияние также является новым символом — двойным вопросительным знаком: ??. Это логический оператор, поведение которого аналогично логическому оператору ИЛИ (символ двойной вертикальной черты). ||).

Разница между ?? и || заключается в том, как оператор обрабатывает нулевые и ложные значения. Большинство разработчиков JavaScript знакомы с тем, как язык обрабатывает нелогические значения при проверке их как true/false (короче, false, 0, null, пустые строки и неопределенное считаются ложными, а все остальное принимает значение true; подробнее здесь). . Мы часто воспользуемся этим, чтобы проверить существование какой-либо вещи, а если она не существует, то используем что-нибудь другое, например:

let meaningOfLife = answer || 42;

Это позволяет установить своего рода значение по умолчанию и быстро проверить наличие чего-либо в answer. Это отлично работает, если мы действительно хотим meaningOfLife по умолчанию — 42, если установлено какое-либо из ложных значений. answer. Но что, если вы хотите вернуться к 42 только в том случае, если существует фактическое нулевое значение (в частности, нулевое или неопределенное)?

?? делает это просто. Ты используешь

let meaningOfLife = answer ?? 42;

Чтобы прояснить это, подумайте о том, чтобы установить 0 в качестве значения answerи как присвоить значение meaningOfLife будет работать, используя || против ?? как в листинге 2. В этом случае мы хотим сохранить 0 в качестве значения, если оно установлено, но использовать 42, если answer на самом деле пуст.

Листинг 2. Нулевое объединение в действии

let answer = 0;
let meaningOfLife = answer ?? 42; // meaningOfLife === 0 - what we want
let meaningOfLife = answer || 42; // meaningOfLife === 42 - not what we want
let answer = undefined;
let meaningOfLife = answer ?? 42; // meaningOfLife === 42 - what we want
let meaningOfLife = answer || 42; // meaningOfLife === 42 - also what we want

String.prototype.matchAll

Спецификация ES11 добавляет к прототипу String новый метод: matchAll. Этот метод применяет регулярное выражение к экземпляру String и возвращает итератор со всеми совпадениями. Например, предположим, что вы хотите просмотреть строку на предмет всех мест, где слово начинается с t или T. Вы можете сделать это, как в листинге 3.

Листинг 3. Использование matchAll

let text = "The best time to plant a tree was 20 years ago. The second best time is now.";
let regex = /(?:^|\s)(t[a-z0-9]\w*)/gi; // matches words starting with t, case insensitive
let result = text.matchAll(regex);
for (match of result) {
  console.log(match[1]);
}

Отбросьте присущую синтаксису регулярных выражений плотность и примите, что регулярное выражение, определенное в листинге 3, найдет слова, начинающиеся с t или T. matchAll() применяет это регулярное выражение к строке и возвращает вам итератор, который позволяет вам просто и легко просматривать результаты и получать доступ к совпадающим группам.

Динамический импорт

ES11 представляет усовершенствование в том, как вы можете импортировать модули, позволяя произвольное размещение импортируемых модулей, загружаемых асинхронно. Это также известно как разделение кода, и мы уже много лет делаем это с помощью инструментов сборки. Динамический импорт — еще один пример того, как спецификация догоняет существующие практики.

Простой пример синтаксиса показан в листинге 4.

Листинг 4. Импорт асинхронного модуля

let asyncModule = await import('/lib/my-module.ts');

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

Обещание.allSettled()

promise.allSettled() Метод позволяет наблюдать за результатами набора обещаний, независимо от того, выполняются они или отвергаются. Это можно противопоставить promise.all()что закончится отказом от обещания или отказом от обещания. promise.allSettled() возвращает массив объектов, описывающих результаты каждого обещания.

Это полезно при просмотре группы несвязанных обещаний. То есть вы хотите знать, что случилось с ними всеми, даже если некоторые из них потерпят неудачу. В листинге 5 приведен пример.

Листинг 5. Пример Promise.allSettled()

let promise1 = Promise.resolve("OK");
let promise2 = Promise.reject("Not OK");
let promise3 = Promise.resolve("After not ok");
Promise.allSettled([promise1, promise2, promise3])
    .then((results) => console.log(results))
    .catch((err) => console.log("error: " + err));

В этом случае лямбда-захват не срабатывает (это было бы, если бы мы использовали promise.all). Вместо этого then выполняется предложение и возвращается массив с содержимым листинга 6. Ключевой вывод здесь заключается в том, что третье обещание выполнено, и мы можем видеть его результат, хотя promise2 до этого не получилось.

Листинг 6. Результаты Promise.allSettled()

[
  {"status":"fulfilled","value":"OK"},
  {"status":"rejected","reason":"Not OK"},
  {"status":"fulfilled","value":"After not ok"}
]

Экспортировать звездчатый синтаксис

Эта функция добавляет возможность export * из модуля. Ты уже мог import * из другого модуля, но теперь вы можете экспортировать его с тем же синтаксисом, как в листинге 7.

Листинг 7. Пример экспорта *

Export * from '/dir/another-module.js'

Это своего рода цепочка модулей, позволяющая экспортировать все из другого модуля изнутри текущего модуля. Полезно, например, если вы создаете модуль, который объединяет другие модули в свой API.

Стандартизация заказов на поступление

Знаете ли вы, что порядок перечисления коллекций в циклах for-in в JavaScript не гарантирован? На самом деле это гарантировалось всеми средами JavaScript (браузерами, Node.js и т. д.), но теперь этот стандарт де-факто был включен в спецификацию. Теория снова имитирует практику.

Развивающаяся спецификация

Одна из самых интересных вещей в работе в индустрии программного обеспечения — это наблюдение за развитием событий. Языки программирования — одно из самых фундаментальных выражений, в котором большая часть философии информатики встречается с реальностью повседневного кодирования. JavaScript (как и другие живые языки) продолжает расти в ответ на эти силы благодаря ежегодному графику выпуска.

Related Posts

Оставить комментарий