JavaScript

5 функций ES2019, которые вы можете использовать сегодня

Spread the love

ECMAScript 2015, также известный как ES6, был основным релизом, для выпуска которого потребовалось шесть лет. С тех пор Технический комитет 39 (ТК39), орган, отвечающий за разработку стандарта ECMAScript, выпускает новую редакцию стандарта каждый год. Этот годовой цикл релизов упростил процесс и быстро сделал доступными новые функции, что приветствовало сообщество JavaScript.

В этом году будет выпущен ECMAScript 2019 (или ES2019 для краткости). Новые функции включают Object.fromEntries(), trimStart(), trimEnd(), flat(), flatMap(), свойство description для объектов Symbol, необязательная переменная в catch и многое другое.

Хорошей новостью является то, что эти функции уже были реализованы в последних версиях Firefox и Chrome. В этом посте мы подробно рассмотрим эти функции и посмотрим, как они обновляют язык.

1. Object.fromEntries()

Преобразование данных из одного формата в другой очень распространено в JavaScript. Чтобы упростить преобразование объектов в массивы, ES2017 ввел метод Object.entries(). Этот метод принимает объект в качестве аргумента и возвращает массив собственных перечисляемых пар свойств строкового ключа объекта в виде [key, value]. Например:

const obj = {one: 1, two: 2, three: 3};

console.log(Object.entries(obj));    
// => [["one", 1], ["two", 2], ["three", 3]]

Но что, если мы хотим сделать обратное и преобразовать список пар ключ-значение в объект? Некоторые языки программирования, такие как Python, предоставляют для этого функцию dict(). В Underscore.js и Lodash также есть функция _.fromPairs.

ES2019 призван привнести аналогичную функцию в JavaScript путем введения метода Object.fromEntries(). Этот статический метод позволяет легко преобразовать список пар ключ-значение в объект:

const myArray = [['one', 1], ['two', 2], ['three', 3]];
const obj = Object.fromEntries(myArray);

console.log(obj);    // => {one: 1, two: 2, three: 3}

Как вы можете видеть, Object.fromEntries() — это просто противоположность Object.entries(). Хотя раньше было возможно достичь того же результата, это было не очень просто:

const myArray = [['one', 1], ['two', 2], ['three', 3]];
const obj = Array.from(myArray).reduce((acc, [key, val]) => Object.assign(acc, {[key]: val}), {});

console.log(obj);    // => {one: 1, two: 2, three: 3}

Имейте в виду, что аргумент, передаваемый Object.fromEntries(), может быть любым объектом, который реализует итеративный протокол, если он возвращает двухэлементный объект в виде массива.

Например, в следующем коде Object.fromEntries() принимает объект Map в качестве аргумента и создает новый объект, ключи и соответствующие значения которого задаются парами в Map:

const map = new Map();
map.set('one', 1);
map.set('two', 2);

const obj = Object.fromEntries(map);

console.log(obj);    // => {one: 1, two: 2}

Метод Object.fromEntries() также очень полезен для преобразования объектов. Рассмотрим следующий код:

const obj = {a: 4, b: 9, c: 16};

// convert the object into an array
const arr = Object.entries(obj);

// get the square root of the numbers
const map = arr.map(([key, val]) => [key, Math.sqrt(val)]);

// convert the array back to an object
const obj2 = Object.fromEntries(map);

console.log(obj2);  // => {a: 2, b: 3, c: 4}

Этот код преобразует значения в объекте в квадратный корень. Для этого сначала он преобразует объект в массив, а затем использует метод map() для получения квадратного корня из значений в массиве. В результате получается массив массивов, которые можно преобразовать обратно в объект.

Другая ситуация, в которой Object.fromEntries() оказывается полезной, — при работе со строкой запроса URL-адреса, как показано в следующем примере:

const paramsString = 'param1=foo&param2=baz';
const searchParams = new URLSearchParams(paramsString);

Object.fromEntries(searchParams);    // => {param1: "foo", param2: "baz"}

В этом коде строка запроса передается в конструктор URLSearchParams(). Затем возвращаемое значение, которое является экземпляром объекта URLSearchParams, передается методу Object.fromEntries(). Результатом является объект, содержащий каждый параметр в качестве свойства.

Метод Object.fromEntries() в настоящее время является предложением этапа 4, что означает, что он готов для включения в стандарт ES2019.

2. trimStart() и trimEnd()

Методы trimStart() и trimEnd() технически совпадают с методами trimLeft() и trimRight(). Эти методы в настоящее время являются предложениями этапа 4 и будут добавлены в спецификацию для согласованности с padStart() и padEnd(). Давайте рассмотрим несколько примеров:

const str = "   string   ";

// es2019
console.log(str.trimStart());    // => "string   "
console.log(str.trimEnd());      // => "   string"

// the same as
console.log(str.trimLeft());     // => "string   "
console.log(str.trimRight());    // => "   string"

Для веб-совместимости trimLeft() и trimRight() останутся псевдонимами для trimStart() и trimEnd().

3. flat() и flatMap()

Метод flat() позволяет вам легко объединять все элементы подмассива в массив. Рассмотрим следующий пример:

const arr = ['a', 'b', ['c', 'd']];
const flattened = arr.flat();

console.log(flattened);    // => ["a", "b", "c", "d"]

Ранее для получения плоского массива вам пришлось бы использовать Reduce() или Concat():

const arr = ['a', 'b', ['c', 'd']];
const flattened = [].concat.apply([], arr);

// or
// const flattened =  [].concat(...arr);

console.log(flattened);    // => ["a", "b", "c", "d"]

Обратите внимание, что если в предоставленном массиве есть пустые слоты, они будут отброшены:

const arr = ['a', , , 'b', ['c', 'd']];
const flattened = arr.flat();

console.log(flattened);    // => ["a", "b", "c", "d"]

flat() также принимает необязательный аргумент, который задает количество уровней, на которые должен быть сведен вложенный массив. Если аргумент не указан, будет использовано значение по умолчанию 1:

const arr = [10, [20, [30]]];

console.log(arr.flat());     // => [10, 20, [30]]
console.log(arr.flat(1));    // => [10, 20, [30]]
console.log(arr.flat(2));    // => [10, 20, 30]

Метод flatMap() объединяет map() и flat() в один метод. Сначала он создает новый массив с возвращаемым значением предоставленной функции, а затем объединяет все элементы подмассива в массив. Пример должен сделать это более понятным:

const arr = [4.25, 19.99, 25.5];

console.log(arr.map(value => [Math.round(value)]));    
// => [[4], [20], [26]]

console.log(arr.flatMap(value => [Math.round(value)]));    
// => [4, 20, 26]

Уровень глубины выравнивания массива равен 1. Если вы хотите удалить элемент из результата, просто верните пустой массив:

const arr = [[7.1], [8.1], [9.1], [10.1], [11.1]];

// do not include items bigger than 9
arr.flatMap(value => {
  if (value >= 10) {
    return [];
  } else {
    return Math.round(value);
  }
});  

// returns:
// => [7, 8, 9]

Помимо текущего обрабатываемого элемента, функция обратного вызова также получит индекс элемента и ссылку на сам массив. Методы flat() и flatMap() в настоящее время являются предложениями этапа 4.

4. Описание свойства для объектов Symbol

При создании Symbol вы можете добавить описание для отладки. Иногда полезно иметь прямой доступ к описанию в вашем коде.

Это предложение ES2019 добавляет свойство описания только для чтения к объекту Symbol, которое возвращает строку, содержащую описание Symbol. Вот некоторые примеры:

let sym = Symbol('foo');
console.log(sym.description);    // => foo

sym = Symbol();
console.log(sym.description);    // => undefined

// create a global symbol
sym = Symbol.for('bar');
console.log(sym.description);    // => bar

5. Опциональная переменная в catch

Переменная в catch в выражении try… catch теперь будет опциональным. Рассмотрим следующий код:

try {
  // использовать функцию, которую браузер, возможно, не реализовал
} catch (unused) {
  // вернуться к уже реализованной функции
}

В этом коде нет смысла для переменной unused в catch. Тем не менее, он все еще должен использоваться, чтобы избежать SyntaxError. Это предложение вносит небольшое изменение в спецификацию ECMAScript, которая позволяет вам пропустить переменную в catch и окружающие ее скобки:

try {
  // использовать функцию, которую браузер, возможно, не реализовал
} catch {
  // сделать что-то, что не заботится о значение thrown
}

Бонус: ES2020 String.prototype.matchAll

Метод matchAll() является предложением ES2020 этапа 4, которое возвращает объект итератора для всех совпадений, включая группы захвата, для регулярного выражения.

Для согласованности с методом match() TC39 выбрал «matchAll» среди других предложенных имен, таких как «matches» или «scan» Руби. Давайте рассмотрим простой пример:

const re = /(Dr\. )\w+/g;
const str = 'Dr. Smith and Dr. Anderson';
const matches = str.matchAll(re);

for (const match of matches) {
  console.log(match);
}

// logs:
// => ["Dr. Smith", "Dr. ", index: 0, input: "Dr. Smith and Dr. Anderson", groups: undefined]
// => ["Dr. Anderson", "Dr. ", index: 14, input: "Dr. Smith and Dr. Anderson", groups: undefined]

Группа захвата в этом регулярном выражении соответствует символам «Dr», за которыми следуют точка и пробел. \w+ соответствует любому символу слова один или несколько раз. А флаг g указывает движку искать шаблон по всей строке.

Раньше вам приходилось использовать метод exec() в цикле для достижения того же результата, что было не очень эффективно:

const re = /(Dr\.) \w+/g;
const str = 'Dr. Smith and Dr. Anderson';
let matches;

while ((matches = re.exec(str)) !== null) {
  console.log(matches);
}

// logs:
// => ["Dr. Smith", "Dr.", index: 0, input: "Dr. Smith and Dr. Anderson", groups: undefined]
// => ["Dr. Anderson", "Dr.", index: 14, input: "Dr. Smith and Dr. Anderson", groups: undefined]

Важно отметить, что хотя метод match() можно использовать с глобальным флагом g для доступа ко всем совпадениям, он не предоставляет группы захвата или индексную позицию совпадений. Для сравнения:

const re = /page (\d+)/g;
const str = 'page 2 and page 10';

console.log(str.match(re));    
// => ["page 2", "page 10"]

console.log(...str.matchAll(re)); 
// => ["page 2", "2", index: 0, input: "page 2 and page 10", groups: undefined] 
// => ["page 10", "10", index: 11, input: "page 2 and page 10", groups: undefined]

Завершение

В этой статье мы подробно рассмотрели несколько ключевых функций, представленных в ES2019, включая Object.fromEntries(), trimStart(), trimEnd(), flat(), flatMap(), свойство description для объектов Symbol и необязательная переменная в catch.

Несмотря на то, что некоторые функции браузеров еще не полностью реализовали эти функции, вы все равно можете использовать их в своих проектах благодаря Babel и другим транспортерам JavaScript.

Темпы развития ECMAScript в последние годы ускорились, и новые функции внедряются и внедряются время от времени, поэтому обязательно ознакомьтесь со списком готовых предложений, чтобы быть в курсе того, что нового. У вас есть несколько советов? Поделитесь ими в комментариях!

Оригинальная статья: Faraz Kelhini 5 ES2019 features you can use today

Была ли вам полезна эта статья?
[1 / 5]

Spread the love
Editorial Team

Recent Posts

Vue 3.4 Новая механика v-model компонента

Краткий перевод: https://vuejs.org/guide/components/v-model.html Основное использование​ v-model используется для реализации двусторонней привязки в компоненте. Начиная с Vue…

11 месяцев ago

Анонс Vue 3.4

Сегодня мы рады объявить о выпуске Vue 3.4 «🏀 Slam Dunk»! Этот выпуск включает в…

11 месяцев ago

Как принудительно пере-отобразить (re-render) компонент Vue

Vue.js — это универсальный и адаптируемый фреймворк. Благодаря своей отличительной архитектуре и системе реактивности Vue…

2 года ago

Проблемы с установкой сертификата на nginix

Недавно, у меня истек сертификат и пришлось заказывать новый и затем устанавливать на хостинг с…

2 года ago

Введение в JavaScript Temporal API

Каким бы ни было ваше мнение о JavaScript, но всем известно, что работа с датами…

2 года ago

Когда и как выбирать между медиа запросами и контейнерными запросами

Все, кто следит за последними событиями в мире адаптивного дизайна, согласятся, что введение контейнерных запросов…

2 года ago