Как преобразовать объекты JavaScript - возможности Object.Keys (), .Values ​​(), .Entries ()

Давайте посмотрим на некоторые мощные методы, которые позволяют преобразовывать данные нашего объекта.

Как мы перебираем объекты? Как мы перебираем все пары ключ-значение, чтобы получить все наши данные?

Традиционно это можно было сделать с помощью цикла for-in:

const obj = { a: 1, b: 2 };

for (const key in obj) {
  console.log("key", key);
  console.log("value", obj[key]);
}

// key a
// value 1
// key b
// value 2

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

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

С помощью некоторых встроенных методов Object мы можем преобразовывать объекты в массивы тремя различными способами. Это методы Object.keys, Object.values и Object.entries.

Object.keys ()

Первым из этих методов, пришедших на язык, был Object.keys. Как видно из названия, он позволяет нам брать ключи объекта и превращать его в массив. Допустим, у нас есть некоторые пользовательские данные, выраженные в виде объекта:

const user = {
  name: "John",
  age: 29,
};

Когда мы используем Object.keys в нашем пользовательском объекте,

console.log(Object.keys(user)); // ["name", "age"]

Получаем массив, где name и age - элементы. Обратите внимание: поскольку ключи в объектах всегда являются строками, когда они становятся элементами массива, они также будут строками.

Практическое использование - Object.keys ()

Но что в этом ценного?

Одна ценная вещь заключается в том, что мы действительно можем имена наших ключей. Раньше у нас не было возможности получить доступ к ключам самих объектов, только к их свойствам. Таким образом, это дает нам новую возможность проверить, существует ли данное свойство.

Итак, теперь, используя Object.keys, как мы можем проверить, включает ли наш объект ключ с определенным именем. В этом случае, возможно, ключ с именем age…

Хорошо, что мы знаем метод массива, чтобы проверить, существует ли данная строка как элемент, - метод includes. Итак, мы можем использовать Object.keys, а затем включить в цепочку включения.

Мы можем сохранить результат этой операции в переменной ageExists и зарегистрировать его:

const ageExists = Object.keys(user).includes("age");
console.log(ageExists);

И мы получаем правду. Так что это хороший способ узнать, существует ли данный ключ на объекте.

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

Таким образом, с помощью карты каждый элемент может называться prop или key. И обратите внимание, что здесь мы должны использовать синтаксис квадратных скобок вместо доступа к свойству точки. Это почему?

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

Object.keys(user).map((key) => user[key]);

А затем поместим полученный массив в переменную с именем values ​​и посмотрим, что мы получим:

const values = Object.keys(user).map((key) => user[key]);
console.log(values); // ["John", 29]

Object.values ​​()

Теперь есть гораздо более простой способ получить значения объекта. Вот для чего мы используем Object.values. Мы можем заменить весь предыдущий код, который мы написали, только Object.values ​​и передать объект, значения свойств которого мы хотим получить:

// const values = Object.keys(user).map(key => user[key])
// console.log(values)

const values = Object.values(user);
console.log(values); // ["John", 29]

И получаем тот же результат.

Практическое использование - Object.values ​​()

Что мы можем сделать с Object.values? Допустим, у нас есть объект, содержащий данные о ежемесячных расходах пользователя:

const monthlyExpenses = {
  food: 400,
  rent: 1700,
  insurance: 550,
  internet: 49,
  phone: 95,
};

Попытайтесь представить, было ли у этого еще больше свойств, чем на самом деле. Как нам легко получить общую сумму всех этих совокупных расходов?

Мы могли бы придумать способ сделать это, используя цикл for in или что-то в этом роде, но это не так просто, как выбросить все значения в один массив. И мы знаем, как легко получить сумму массива чисел с помощью reduce.

Посмотри, сможешь ли ты сделать это самостоятельно. Как бы вы сложили Object.values и reduce, чтобы получить ежемесячную сумму всех расходов Джона…

Сначала мы могли бы создать переменную monthlyTotal, получить массив значений стоимости каждого расхода. А затем, используя метод reduce, мы можем просуммировать все в одну строку. Сначала наше возвращаемое значение будет числом, поэтому наше начальное значение будет 0. Затем у нас есть аккумулятор, и каждый элемент будет расходом. Сокращение для выполнения этой операции - acc + expense. И поскольку у нас есть неявный возврат с нашей стрелочной функцией, аккумулятор всегда будет возвращаться:

const monthlyTotal = Object.values(monthlyExpenses).reduce(
  (acc, expense) => acc + expense,
  0
);

console.log(monthlyTotal); // 2794

В результате наша ежемесячная сумма составляет 2794. Это, вероятно, настолько лаконично, насколько может быть такая операция. Итак, Object.values отлично подходит, когда вам нужен более гибкий способ работы со всеми значениями данного объекта.

Практическое использование - Object.entries ()

И, наконец, если нам нужен весь объект, как ключи, так и значения, сопоставленные с одним массивом, мы используем Object.entries:

console.log(Object.entries(user)); // (2) [Array(2), Array(2)]

Это дает нам интересный результат - массив массивов. Так какая польза от ключей и значений?

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

const users = {
  "1": {
    name: "John",
    age: 29,
  },
  "2": {
    name: "Jane",
    age: 42,
  },
  "3": {
    name: "Fred",
    age: 17,
  },
};

И предположим, что нам нужно получить очень конкретные данные от этого объекта, скажем, мы просто хотели получить данные пользователя, их имя, возраст и идентификатор, но специально для пользователей старше 20 лет.

Если бы нам нужно было полагаться только на методы объекта, у нас не было бы возможности получить эти данные из вложенного объекта.

Но с помощью Object.entries, поскольку он преобразует наш объект в массив, мы можем решить эту проблему, без проблем.

Сначала давайте передадим пользователей в Object.entries и console.log, чтобы увидеть, что мы получим, поскольку мы собираемся получить вдвое больше данных, чем Object.keys или Object.values:

console.log(Object.entries(users));
// 0: (2) ["1", {…}]
// 1: (2) ["2", {…}]
// 2: (2) ["3", {…}]

Для каждого вложенного массива у нас есть ключ или идентификатор пользователя в качестве первого элемента и значение или объект пользователя в качестве второго элемента.

Замена карты / фильтра на одно сокращение

Теперь мы можем связать любой метод массива, который нам нужен для выполнения работы. Итак, давайте подумаем, что мы хотим сделать: нам нужно преобразовать данные в массив объектов, который мы также хотим фильтровать на основе условия. Итак, основываясь на этих двух критериях, подумайте на секунду и угадайте, какой метод массива нам нужно использовать ...

Вы могли бы сказать, что нам нужно использовать два метода, map и filter, потому что мы хотим как преобразовать, так и отфильтровать массив. Таким образом, можно было бы объединить в цепочку map, а затем отфильтровать. Однако позвольте дать вам быстрый совет по выполнению преобразования карты и фильтра. Основываясь на нашем глубоком погружении в оба метода, что мы знаем о них обоих? Что они оба могут быть реализованы с помощью reduce. Так как это обе операции сокращения, мы можем заменить их обе одной операцией сокращения. Фактически, в большинстве случаев, когда вы думаете, что вам нужно создать цепочку методов массива, вы можете заменить их на reduce.

Итак, используя reduce, мы создадим базовую структуру. Мы создадим функцию обратного вызова с аккумулятором, а затем предоставим начальное значение, основанное на конечном значении, которое мы хотим получить, в виде массива:

Object.entries(users).reduce((acc) => {}, []);

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

Object.entries(users).reduce((acc, [id, user]) => {}, []);

А теперь, чтобы условно поместить элемент массива в наш последний массив, если его свойство age больше 20, мы можем добавить оператор if. Если user.age > 20, то протолкнуть объект в аккумулятор. Чтобы создать этот объект, мы можем расширить его свойства и добавить id в конце. Поскольку id будет использоваться в свойстве и значении, мы будем использовать сокращение объекта:

Object.entries(users).reduce((acc, [id, user]) => {
  if (user.age > 20) {
    acc.push({ ...user, id });
  }
}, []);

И, наконец, нам просто нужно вернуть аккумулятор в конце. Давайте просто поместим массив результатов в новую переменную с именем usersOver20 и запишем ее в журнал.

const usersOver20 = Object.entries(users).reduce((acc, [id, user]) => {
  if (user.age > 20) {
    acc.push({ ...user, id });
  }
  return acc;
}, []);
console.log(usersOver20);

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

Резюме

Когда вы находитесь в ситуации, когда у вас есть более статическая структура данных, такая как объект, но вам нужно управлять его содержимым более динамично, попробуйте использовать один из методов, которые мы здесь рассмотрели, либо Object.keys, либо значения или записи.

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

Хотите стать мастером JS? Присоединяйтесь к 2020 JS Bootcamp 🏕️

Follow + Say Hi! 🎨 TwitterInstagramreedbarger.comcodeartistry.io