[Перевод] 5 возможностей JavaScript ES12, которыми стоит воспользоваться уже сегодня

Стандарт ECMAScript 2021 (12 редакция) выпущен 22 июня 2021 года. Вместе с ним появились новые возможности и новые синтаксические конструкции. Все эти улучшения направлены на то, чтобы сделать JavaScript надёжнее и стабильнее, чтобы разработчикам легче было делать своё дело.

8ns01-8nj9jykn7rja5vhi4jfli.jpeg

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

1. Разделители разрядов чисел


Разделители разрядов чисел позволяют записывать числовые литералы с использованием символов подчёркивания, что улучшает читабельность чисел. Система автоматически удаляет эти символы при подготовке кода к запуску. В следующем коде демонстрируется пример использования разделителей.

// Десятичное число, разряды которого разделены символом подчёркивания.
let n1 = 1_000_000_000;
console.log(n1); // Выведет: 1000000000

// Десятичное число, разряды которого разделены символом подчёркивания.
let n2 = 1_000_000_000.150_200
console.log(n2); // Выведет: 1000000000.1502

// Шестнадцатеричное число, байты которого разделены символом подчёркивания.
let n3 = 0x95_65_98_FA_A9
console.log(n3); // Выведет: 641654651561

// BigInt-число, разряды которого разделены символом подчёркивания.
let n4 = 155_326_458_156_248_168_514n
console.log(n4); // This will print: 155326458156248168514n


2. Метод String.prototype.replaceAll ()


Новый метод строковых объектов replaceAll() позволяет заменить на что либо все вхождения подстроки в строке. При использовании строкового метода replace() осуществляется лишь замена первого вхождения искомого значения. А метод replaceAll() позволяет заменить все вхождения такого значения. Вот пример:

// Объявляем константу, хранящую некое строковое значение.
const orgStr = 'JavaScript, often abbreviated as JS, is a programming language that conforms to the ECMAScript specification. JavaScript is high-level, often just-in-time compiled and multi-paradigm.';

// Для того чтобы заменить в исходной строке лишь первое вхождение искомой подстроки и сформировать новую строку - воспользуемся методом replace().
let newStr = orgStr.replace('JavaScript', 'TypeScript');
console.log(newStr);

// Для замены всех вхождений искомой строки воспользуемся методом replaceAll().
let newStr2 = orgStr.replaceAll('JavaScript', 'TypeScript');
console.log(newStr2);


3. Метод Promise.any () и объект AggregateError


Метод Promise.any() можно назвать полной противоположностью метода Promise.all(). Promise.any(), при передаче ему итерируемого объекта с промисами, возвращает промис со значением первого успешно выполненного промиса. Если ни один из промисов не разрешён — метод возвращает сведения об ошибках, в частности — объект AggregateError. А Promise.all() ждёт разрешения всех промисов. Есть и другие методы объекта Promise. Например — Promise.allSettled(), который ожидает успешного завершения или отклонения всех переданных ему промисов.

Рассмотрим пример:

// Создаём объект Promise.
const promise1 = new Promise((resolve, reject) => {
    // Разрешить промис через 2 секунды.
    setTimeout(() => resolve("The first promise has been resolved."), 2000);
});

// Создаём объект Promise.
const promise2 = new Promise((resolve, reject) => {
    // Разрешить промис через 1 секунду.
    setTimeout(() => resolve("The second promise has been resolved."), 1000);
});

// Создаём объект Promise.
const promise3 = new Promise((resolve, reject) => {
    // Разрешить промис через 3 секунды.
    setTimeout(() => resolve("The third promise has been resolved."), 3000);
});

(async function () {
    const data = await Promise.any([promise1, promise2, promise3]);
    // Выводим данные, возвращённые из первого разрешённого промиса.
    console.log(data);
    // Предыдущая команда выведет следующее: The second promise has been resolved.
})()


Если все промисы были отклонены — будет возвращён объект AggregateError, содержащий сведения об ошибках. Обратитесь к следующему примеру для того чтобы разобраться с тем, как обрабатывать подобные ошибки:

// Создаём объект Promise.
const promise1 = new Promise((resolve, reject) => {
    // Отклонить промис через 1 секунду.
    setTimeout(() => reject("The first promise has been rejected."), 1000);
});

// Создаём объект Promise.
const promise2 = new Promise((resolve, reject) => {
    // Отклонить промис через 500 миллисекунд.
    setTimeout(() => reject("The second promise has been rejected."), 500);
});

// Попытаемся выполнить промисы.
(async function () {
    try {
        const data = await Promise.any([promise1, promise2]);
        console.log(data);
    } catch (error) {
        // Если все промисы отклонены, мы попадём в этот блок try-catch, где 
        // можно будет обработать ошибки, с которыми завершилась работа промисов.
        console.log("Error: ", error);
    }
})();


4. Логические операторы присваивания


В ECMAScript 2021 появились три новых оператора, которые представляют собой комбинацию оператора присваивания и логических операторов.

  • Логический оператор присваивания ИЛИ (OR): ||=.
  • Логический оператор присваивания И (AND): &&=.
  • Логический оператор присваивания с проверкой значений на null и undefined: ??=.


▍4.1. Оператор ||=


Оператор ||= принимает два операнда и назначает правый операнд левому только в том случае, если левый операнд является ложным. Вот пример:

// Оператор ||= проверит, не является ли ложным (0) значение songsCount.
// Если это так, правый операнд будет записан в переменную, находящуюся в левой части выражения.
let myPlaylist = {songsCount: 0, songs:[]};
myPlaylist.songsCount ||= 100;
console.log(myPlaylist); // Выведет: {songsCount: 100, songs: Array(0)}


Этот оператор работает по сокращённой схеме вычислений. Он эквивалентен следующему выражению, в котором используется логический оператор ИЛИ:

a || (a = b)


▍4.2. Оператор &&=


Оператор &&= присваивает правый операнд левому только в том случае, если значение, находящееся слева, является истинным. Рассмотрим пример:

// Оператор &&= проверит, является ли значение filesCount истинным.
// Если это так - правый операнд будет присвоен левому.
let myFiles = {filesCount: 100, files:[]};
myFiles.filesCount &&= 5;
console.log(myFiles); // Выведет: {filesCount: 5, files: Array(0)}


Оператор &&= тоже работает по сокращённой схеме вычислений. Этот оператор эквивалентен следующему выражению, в котором используется логический оператор И:

a && (a = b)


▍4.3. Оператор ?=


Оператор ??= присвоит правый операнд левому только в том случае, если левый оператор представлен значением null или undefined. Например:

// Оператор ??= проверит, равняется ли lastname null или undefined.
// Если это так - правый операнд будет присвоен левому.
let userDetails = {firstname: 'Katina', age: 24}
userDetails.lastname ??= 'Dawson';
console.log(userDetails); // Выведет: {firstname: 'Katina', age: 24, lastname: 'Dawson'}


5. Приватные методы экземпляров классов и методы доступа к свойствам


Свойства и методы экземпляров классов в JavaScript, по умолчанию, общедоступны. Но теперь можно создавать приватные методы и свойства с использованием префикса #. Доступны они только изнутри экземпляра класса. Вот как пользоваться приватными методами:

// Создадим класс User.
class User {
    constructor() {}

    // Приватный метод можно создать, поместив '#' перед
    // именем метода.
    #generateAPIKey() {
        return "d8cf946093107898cb64963ab34be6b7e22662179a8ea48ca5603f8216748767";
    }

    getAPIKey() {
        // Обратиться к приватному методу можно, поставив '#' перед
        // именем метода.
        return this.#generateAPIKey();
    }
}

const user = new User();
const userAPIKey = user.getAPIKey();
console.log(userAPIKey); // Выведет: d8cf946093107898cb64963ab34be6b7e22662179a8ea48ca5603f8216748767


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

Объявить приватный геттер можно так:

get #newAccountPassword() {}


Так можно объявить приватный сеттер:

set #generateAccountPassword(newPassword) {}


Вот как ими пользоваться:

// Создадим класс Str.
class Str {
    // Приватные свойства можно создавать, помещая '#'
    // перед их именами.
    #uniqueStr;

    constructor() {}

    // Приватный сеттер можно создать, поместив '#' перед
    // его именем.
    set #generateUniqueStringByCustomLength(length = 24) {
        const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        let randomStr = "";

        for (let i = 0; i < length; i++) {
            const randomNum = Math.floor(Math.random() * characters.length);
            randomStr += characters[randomNum];
        }

        this.#uniqueStr = randomStr;
    }

    // Общедоступный сеттер
    set setRandomString(length) {
        this.#generateUniqueStringByCustomLength = length;
    }

    // Приватный геттер можно создать, поместив '#' перед
    // его именем.
    get #fetchUniqueString() {
        return this.#uniqueStr;
    }

    // Общедоступный геттер
    get getRandomString() {
        return this.#fetchUniqueString;
    }
}

const str = new Str();
// Вызываем общедоступный сеттер, который обратится к приватному сеттеру,
// находящемуся в том же объекте, что и он.
str.setRandomString = 20;

// Вызываем общедоступный геттер, который обратится к приватному геттеру,
// находящемуся в том же объекте, что и он.
const uniqueStr = str.getRandomString;
console.log(uniqueStr); // Выводит случайную строку каждый раз, когда геттер вызывают после вызова сеттера


Итоги


Теперь вы знаете, как пользоваться некоторыми новыми возможностями JavaScript ES12 (ECMAScript 2021). А значит — пришло время применить эти знания на практике.

Пользуетесь ли вы возможностями JavaScript ES12 в своих проектах?

image-loader.svg

© Habrahabr.ru