Как сравнить значения двух объектов js
Перейти к содержимому

Как сравнить значения двух объектов js

  • автор:

Пять различных способов глубокого сравнения JavaScript объектов

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

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

В этой статье мы рассмотрим пять различных способов определения равенства объектов JavaScript.

Два типа равенств в JavaScript

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

  • Ссылочное равенство: Определяет, ссылаются ли два предоставленных операнда на одну и ту же ссылку/экземпляр объекта.
  • Глубокое равенство: Определяет, равны ли объекты, сравнивая каждое свойство в операндах.

Ссылочное равенство можно определить с помощью операторов равенства, таких как строгое равенство (===) или принудительное равенство (==), а также с помощью функций Object.is(), но определить глубокое равенство довольно сложно, поскольку объекты могут быть вложенными. Однако следующие пять способов выполнения объектных сравнений облегчают работу разработчиков, когда требуется глубокое сравнение равенств.

Ручное сравнение

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

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

const person1 =  
"firstName": "John",
"lastName": "Doe",
"age": 35
>;

const person2 =
"firstName": "John",
"lastName": "Doe",
"age": 35,
>;

const isDeepEqual = (object1, object2) =>

const objKeys1 = Object.keys(object1);
const objKeys2 = Object.keys(object2);

if (objKeys1.length !== objKeys2.length) return false;

for (var key of objKeys1)
const value1 = object1[key];
const value2 = object2[key];

const isObjects = isObject(value1) && isObject(value2);

if ((isObjects && !isDeepEqual(value1, value2)) ||
(!isObjects && value1 !== value2)
)
return false;
>
>
return true;
>;

const isObject = (object) =>
return object != null && typeof object === "object";
>;

console.log(isDeepEqual(person1, person2)); //true

Метод JSON.stringify()

Этот метод является скорее трюком, который мы можем использовать для определения того, являются ли два объекта глубоко равными или нет. Несмотря на то, что JavaScript не имеет готового решения для сравнения двух объектов, он без проблем сравнивает две строки. Поэтому в данном методе мы преобразуем наши два объекта в строки с помощью метода JSON.stringify() и сравним два значения, чтобы определить, равны ли объекты в глубину. Даже если объекты имеют вложенные свойства, этот метод может справиться и с ними. Важно отметить, что в данном методе используется строгое равенство ( === ) для атрибутов, поэтому значения возраста 35 и 35 не будут равны.

const person1 =  
"firstName": "John",
"lastName": "Doe",
"age": 35
>

const person2 =
"firstName": "John",
"lastName": "Doe",
"age": 35
>

JSON.stringify(person1) === JSON.stringify(person2); // true

Однако у этого метода есть один недостаток. Возьмём приведённый выше пример и изменим порядок следования атрибутов в объекте person2 .

const person2=  
"age": 35,
"firstName": "John",
"lastName": "Doe"
>

Поскольку атрибуты объектов и их значения не изменились, то при сравнении объектов мы ожидаем возврата true . Поскольку в этот раз сгенерированные строки отличаются из-за разницы в порядке следования, сравнение вернёт false .

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

Сравнения с помощью библиотеки Lodash

Известная библиотека Lodash также предоставляет метод для определения глубокого равенства между двумя объектами. Используя метод isEqual() из этой библиотеки, мы можем выполнить глубокое сравнение между заданными операндами. Он вернёт логическое значение, показывающее, равны ли операнды, на основе JavaScript-строгого равенства ( === ) по всем атрибутам двух заданных объектов.

const _ = require('lodash'); 

const person1 =
"firstName": "John",
"lastName": "Doe",
"age": 35
>

const person2 =
"firstName": "John",
"lastName": "Doe",
"age": 35
>

_.isEqual(person1, person2); // true

Согласно документации Lodash, этот метод поддерживает массивы, буферы массивов, объекты даты и т.д. В качестве бонуса мы можем загрузить этот метод в виде отдельного модуля npm.

Сравнения с помощью библиотеки deep-equal

Библиотека deep-equal — ещё один очень популярный модуль NPM с более чем 11 млн. еженедельных загрузок. Эта библиотека предоставляет функциональность для определения глубокого равенства между двумя объектами.

Метод deepEqual() из библиотеки принимает три параметра. Первые два — это сравниваемые операнды, а третий параметр — необязательный параметр options . С помощью опции мы можем указать, использовать ли для сравнения узлов листа строгое равенство ( === ) или принудительное равенство ( == ). По умолчанию для сравнения узлов листа используется принудительное равенство.

const deepEqual = require('deep-equal'); 

const person1 =
"firstName": "John",
"lastName": "Doe",
"age": 35
>

const person2 =
"firstName": "John",
"lastName": "Doe",
"age": "35"
>
deepEqual(person1, person2); // true

Обратите внимание, что в объекте person1 значение age является числом, а в объекте person2 — строкой . Поскольку параметр strict по умолчанию равен false , библиотека deep-equal использует принудительное равенство для узлов листа, поэтому данная функция возвращает true . Если параметр strict функции установлен в true , то данный метод вернёт false .

const person2 =  
"firstName": "John",
"lastName": "Doe",
"age": "35"
>

deepEqual(person1, person2, strict: true>); // false

//Когда значения person2 обновлены с теми же типами данных, что и person1.
const person2 =
"firstName": "John",
"lastName": "Doe",
"age": 35
>

deepEqual(person1, person2, strict: true>); // true

Методы, специфичные для конкретного фреймворка

Некоторые JavaScript-фреймворки, такие, как Angular и Nodejs, предоставляют встроенную функциональность для определения глубокого равенства в своих фреймворках.

    Node.js: assert.deepStrictEqual(actual, expected, message) Метод deepStrictEqual() , предоставляемый модулем assert, является встроенным методом в Node.js, принимающий три параметра: два операнда и сообщение в качестве необязательного параметра, которое будет использоваться при возникновении ошибки, если два операнда не равны. Этот метод проверяет строгое равенство на узлах листа. Он вернёт неопределённое значение, если операнды равны, и выдаст ошибку, если они не являются глубоко и строго равными.

const assert = require('assert'); 

const person1 =
"firstName": "John",
"lastName": "Doe",
"age": 35
>

const person2 =
"firstName": "John",
"lastName": "Doe",
"age": 35
>

console.log(assert.deepStrictEqual(person1, person2)); //true
var person1 =  
firstName: "John",
lastName: "Doe",
age: 35,
>;

var person2 =
firstName: "John",
lastName: "Doe",
age: 35,
>;

console.log(angular.equals(person1, person2)); //true

Заключение

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

Надеюсь, эта статья поможет вам принять правильное решение. Спасибо, что прочитали.

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

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

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

Для сравнения объектов с помощью Lodash следует использовать функцию isEqual() . Эта функция позволяет сравнивать два значения и возвращает true , если они равны, и false в противном случае. Пример:

const _ = require('lodash'); const obj1 =  a: 1, b: 2 >; const obj2 =  a: 1, b: 2 >; const obj3 =  a: 1, b: 3 >; console.log(_.isEqual(obj1, obj2)); // true console.log(_.isEqual(obj1, obj3)); // false 

Здесь мы использовали функцию isEqual() из библиотеки Lodash для сравнения объектов obj1 и obj2 . Функция вернула true , потому что объекты содержат одинаковые свойства с одинаковыми значениями. Затем мы сравнили объекты obj1 и obj3 , и функция вернула false , т.к. они содержат разные значения свойства b .

Проверка двух объектов на идентичность

Есть задача по JavaScript Нужно полностью сравнить два объекта на идентичность их свойств. Порядок свойств в объекте не важен. Если значением какого-то свойства объекта является массив или объект, то начать сверять и их у обоих объектов. Объект в свойстве другого объекта нужно сверять рекурсивно. При сверке объектов — последовательность свойств не важна, но при сверке массивов, важна последовательность элементов, то есть массивы: [1,2,3,4] и [2,1,3,4] не равны, так как, хотя и имеют одинаковые значения, отличаются в последовательности этих значений. Полного сравнения объектов я смог добиться, но если в свойстве объекта массив, то каким бы он не был всегда возвращается true. Свойства сравнивал через valueOf для того случая, если свойством будет дата, что бы она сравнивалась корректно.

function deepEqual (obj1, obj2) < if(obj1 === obj2)< return true; >else < if(Object.keys(obj1).length != Object.keys(obj2).length)< // Проверка на одинаковое количество свойств return false; >for(var propName in obj1) < if (! obj2.hasOwnProperty(propName)) < // Есть ли свойства в обоих объектах return false; >if(obj1[propName].valueOf() !== obj2[propName].valueOf()) < // Одинаковы ли значения свойст if(! deepEqual(obj1[propName], obj2[propName]) )< // проверка объекта в объекте return false; >> > > return true; > 

Вот данные для проверки Первый объект

 var objA = < prop1: 'value1', prop2: 'value2', prop3: 'value3', prop4: < subProp1: 'sub value1', subProp2: < subSubProp1: 'sub sub value1', subSubProp2: [1, 2, , 4, 5] > >, prop5: 1000, prop6: new Date(2016, 2, 10) >; 

Второй объект

 var objB = < prop5: 1000, prop3: 'value3', prop1: 'value1', prop2: 'value2', prop6: new Date('2016/03/10'), prop4: < subProp2: < subSubProp1: 'sub sub value1', subSubProp2: [1, 2, , 4, 5] >, subProp1: 'sub value1' > >; 

В чем ошибка? Нужно ли для проверки массивов создавать новую функцию?

Отслеживать

задан 19 авг 2017 в 9:42

11 1 1 золотой знак 1 1 серебряный знак 1 1 бронзовый знак

Легче всего сравнивать строки, поэтому я в своих проектах просто использую JSON.stringify() и уже получившиеся строки сравниваю

– user182722

19 авг 2017 в 10:01

@Masiama дешево и сердито

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

Нужно обработать на фронте,добавлять в объект новый children если он пришел с сервера.

  • Вопрос задан более трёх лет назад
  • 10982 просмотра

Комментировать

Решения вопроса 0

Ответы на вопрос 3

function deepEqual(obj1, obj2) < if (typeof obj1 !== "object" || typeof obj2 !== "object") < return false; >if (obj1 === undefined || obj2 === undefined) < return false; >if (obj1 === null || obj2 === null) < return false; >let obj1Keys = Object.keys(obj1); let obj2Keys = Object.keys(obj2); if (obj1Keys.length !== obj2Keys.length) < return false; >for (let i = 0; i < obj1Keys.length; i++) < if (obj2Keys.includes(obj1Keys[i]) === false) < return false; >> for (let i = 0; i < obj1Keys.length; i++) < if (typeof obj1[obj1Keys[i]] === "object") < return deepEqual(obj1[obj1Keys[i]], obj2[obj1Keys[i]]); >if (obj1[obj1Keys[i]] !== obj2[obj2Keys[i]]) < return false; >> return true; >

Ответ написан более трёх лет назад

Комментировать

Нравится 2 Комментировать

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *