Как сравнить два объекта js

от admin

Как сравнивать объекты в JavaScript

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

Однако что, если вы хотите проверить, имеют ли два объекта идентичные ключи и значения? Есть 3 подхода.

Сравнить ключи и значения на прямую

Один простой подход — перебрать каждый ключ и значение в двух объектах и проверить их равенство.

Использовать JSON.stringify()

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

Вы можете сделать objectsEqual() рекурсивным, но в таком случае нужно быть осторожным с бесконечной рекурсией. Простой способ сравнить, являются ли два POJO полностью равными, — это сравнить их представления JSON с помощью JSON.stringify()

Функция JSON.stringify() имеет несколько ограничений, которые делают ее не универсальным выбором для проверки полного равенства. Во-первых, важен порядок определения свойств:

Во-вторых, не все типы могут быть представлены в JSON. Функция JSON.stringify() преобразует даты в строки и игнорирует ключи, значения которых не определены, что может привести к неожиданным результатам.

Использовать Lodash isEqual()

isEqual() — это наиболее изощренный способ сравнения двух объектов. Он обрабатывает широкий спектр крайних случаев и избегает многих ошибок предыдущих двух подходов.

Как сравнить два объекта js

Копирование объектов

В отличие от данных примитивных типов данные объектов копируются по ссылке. Что это значит? Рассмотрим следующий пример:

Вначале определяется обычный объект tom с одним свойством name . Затем присваиваем значение этого объекта константе bob

В данном случае константа bob получае ссылку или условно говоря адрес константы tom , поэтому после этого присвоения обе константы по сути указывают на один и тот же объект в памяти. Соответственно изменения, произведенные через одну константу:

Затронут и другую константу — tom :

Более того, добавим к объекту новое свойство через одну из констант:

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

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

Метод Object.assign

Метод Object.assign() принимает два параметра:

Первый параметр — target представляет объект, в который надо скопировать свойства. Второй параметр — . sources — набор объектов, из которых надо скопировать свойства (то есть мы можем скопировать свойства сразу из нескольких объектов)

Возвращает метод объект target, в который скопированы свойства из объектов sources .

В данном случае вызов Object.assign(<>, tom) означает, что мы копируем данные из объекта tom в пустой объект <> . Результатом этого копирования стал объект bob . Причем это совсем другой объект, нежели tom . И любые изменения с константой bob здесь никак не затронут константу tom .

Консольный вывод программы:

Копирование из нескольких объектов

Подобным образом можно копировать данные из нескольких объектов:

Здесь копируются все свойства из объектов tom и sam в объект person. В итоге после копирования объект person будет иметь три свойства.

Копирование одноименных свойств

Если объекты, из которых выполняется копирование, содержат одинаковые свойства, то свойства из последних объектов замещают свойства предыдущих:

Здесь оба объекта — tom и sam содержат свойство age , но в объекте person свойство age равно 45 — значение из объекта sam, потому что копирование из объекта sam произодится в последнюю очередь.

Копирование свойств-объектов

Несмотря на то, что Object.assign() прекрасно работает для простых объектов, но что будет, если свойство копируемого объекта также представляет объект:

Здесь свойство company объекта tom представляет объект с одним свойством. И при копировании объект bob получит не копию значения tom.company , а ссылку на этот объект. Поэтому изменения bob.company затронут и tom.company .

Копирование объекта с помощью spread-оператора

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

В данном случае объекту bob передаются копии свойств объекта tom.

Если какие-то свойства нового объекта должны иметь другие значения (как в примере выше свойство name), то их можно указать в конце:

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

Читать:
Как преобразовать изображение в 16 бит формат в фотошопе

Тем не менее если объекты содержат вложенные объекты, то эти вложенные объекты при копировании опять же по сути будут представлять ссылки на один и тот же объект:

Сравнение объектов

Сравним два объекта с помощью стандартных операций сравнения и эквивалентности:

Оба оператора в данном случае возвратят значение false , то есть объекты не равны. Причем даже если значения свойств объектов будет одинаковым, то мы все равно в обоих случаях получим false

Однако, что будет, если обе константы (переменных) хранят ссылку на один и тот же объект:

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

How to Compare Objects in JavaScript

In JavaScript, objets are always stored by reference. That means one object is strictly equal another only if they both point to the same object in memory.

However, what if you want to check whether two POJOs have the same data? In other words, the same keys and values? Here's 3 possible approaches.

Keys and Values Shallow Equal

One simple approach is to iterate through each key and value in the two objects and check if the keys and values are strictly equal.

Deep Equality using JSON.stringify()

The previous section shows how to compare objects by checking if the two objects' keys and values are strictly equal. But what if one of the values is an object?

You can make objectsEqual() recursive, but then you need to be careful about infinite recursion. An easy way to compare whether two POJOs are deeply equal is comparing their JSON representations using JSON.stringify() :

The JSON.stringify() function comes with a few limitations that make it a lackluster choice for checking deep equality. First, key order matters:

Second, not all types are representable in JSON. The JSON.stringify() function converts dates to strings, and ignores keys whose value is undefined , which can lead to surprising results.

Using Lodash's isEqual()

Lodash's isEqual() function is the most sophisticated way to compare two objects. It handles a wide variety of edge cases and avoids a lot of the pitfalls of the previous two approaches.

# How to Compare 2 Objects in JavaScript ��

Objects are reference types so you can’t just use === or == to compare 2 objects. One quick way to compare if 2 objects have the same key value, is using JSON.stringify . Another way is using Lodash isEqual function ��

# Deep Nested Comparison

Yup, the 2 ways also work for deep nested objects.

# Which one should I use?

Well that depends. For JSON.stringify() , the order matters. So if the key-value pair are ordered differently in the two objects but are the same, it will return false. Whereas it doesn’t matter in Lodash isEqual , it will return true as along as the key-value pair exists.

Here’s my recommendation. For a quick and dirty solution, I’d use JSON.stringify() . But for a more robust solution that cover more of those odd edge cases, use the Lodash way.

# Community Suggestions

# ES6 Way for comparing 2 objects

This is a solution suggested by @mustafauzun0

. Few things to note though, it won’t work with nested objects and the order of the keys are important. The idea behind this is similar to the stringify way. It coverts the object into a string and compare if the strings are a match. Essentially it’s comparing the equality of two strings. That’s why the order matters.

# JSON.stringify vs Lodash’s isEqual Performance

Cole Turner: Worth noting that objects don’t guarantee sort order, and stringify is going to cost more in performance because it has to serialize the whole object whereas lodash can exit early if it finds a mismatched key. This comes up in interviews ��

blnkdotspace: Lodash is considerably faster. Because lodash will quit soon as it reaches the first difference, but stringify goes right till the end unnecessarily. If you have small arrays it’s okay but for my personal use cases with more than 1000 events/products in a list I wouldn’t ever use Stringify.

Related Posts