Оператор строгого равенства скажет вам, если два типа объектов равны. Однако есть ли способ определить, равны ли два объекта, так же, как значение хэш-кода в Java?
Вопрос переполнения стека Есть ли какая-либо функция hashCode в JavaScript? похож на этот вопрос, но требует более академического ответа. Приведенный выше сценарий демонстрирует, почему это необходимо, и мне интересно, есть ли какое-либо эквивалентное решение .
javascript
object
equals
hashcode
Сообщество
источник
источник
a.hashCode() == b.hashCode()
это не значит, чтоa
оно равноb
. Это необходимое условие, а не достаточное.Ответы:
Краткий ответ
Ответ прост: нет, нет универсальных средств для определения того, что объект равен другому в том смысле, который вы имеете в виду. Исключение составляют случаи, когда вы строго думаете о том, что объект не имеет типов.
Длинный ответ
Концепция заключается в методе Equals, который сравнивает два разных экземпляра объекта, чтобы указать, равны ли они на уровне значения. Тем не менее, это зависит от конкретного типа, чтобы определить, как
Equals
метод должен быть реализован. Итеративного сравнения атрибутов, которые имеют примитивные значения, может быть недостаточно, вполне могут быть атрибуты, которые не должны рассматриваться как часть значения объекта. Например,В этом вышеприведенном случае
c
не очень важно определить, являются ли какие-либо два экземпляра MyClass равными, единственнымиa
иb
важными. В некоторых случаяхc
может варьироваться между экземплярами и все же не быть значимым во время сравнения.Обратите внимание, что эта проблема применяется, когда члены сами могут быть экземплярами типа, и каждый из них должен иметь средства определения равенства.
Еще более усложняется то, что в JavaScript различие между данными и методами размыто.
Объект может ссылаться на метод, который должен вызываться как обработчик события, и это, вероятно, не будет считаться частью его «состояния значения». Тогда как другому объекту вполне может быть назначена функция, которая выполняет важные вычисления и тем самым отличает этот экземпляр от других просто потому, что ссылается на другую функцию.
Как насчет объекта, у которого один из существующих методов-прототипов переопределен другой функцией? Можно ли считать его равным другому экземпляру, который в остальном идентичен? На этот вопрос можно ответить только в каждом конкретном случае для каждого типа.
Как указывалось ранее, исключение будет представлять собой объект строго типизированного типа. В этом случае единственный разумный выбор - итеративное и рекурсивное сравнение каждого члена. Даже тогда нужно спросить, какова «ценность» функции?
источник
_.isEqual(obj1, obj2);
.equals
метода не является тривиальной, поэтому есть такая тема, посвященная эффективной Java .javascript equality object
, получил ответ, взял однострочник из комментария @chovy. спасибоangular.equals
Зачем изобретать велосипед? Дайте Лодаш попробовать. Он имеет ряд обязательных функций, таких как isEqual () .
Он будет грубо проверять каждое значение ключа - как и другие примеры на этой странице - используя ECMAScript 5 и встроенную оптимизацию, если они доступны в браузере.
Примечание. Ранее этот ответ рекомендовал Underscore.js , но lodash проделал лучшую работу по исправлению ошибок и последовательному решению проблем.
источник
Оператор равенства по умолчанию в JavaScript для объектов возвращает true, если они ссылаются на одно и то же место в памяти.
Если вам требуется другой оператор равенства, вам нужно добавить
equals(other)
метод или что-то подобное в ваши классы, и специфика вашей проблемной области определит, что именно это означает.Вот пример игры в карты:
источник
{x:1, y:2}
! =={y:2, x:1}
Если вы работаете в AngularJS ,
angular.equals
функция определит, равны ли два объекта. В Ember.js используйтеisEqual
.angular.equals
- Смотрите документы или источник для получения дополнительной информации об этом методе. Это делает глубокое сравнение на массивах тоже.isEqual
- см. Документы или источник для получения дополнительной информации об этом методе. Это не делает глубокое сравнение на массивах.источник
Это моя версия. Он использует новую функцию Object.keys, которая представлена в ES5, и идеи / тесты из + , + и + :
источник
objectEquals([1,2,undefined],[1,2])
возвращаетсяtrue
objectEquals([1,2,3],{0:1,1:2,2:3})
также возвращаетtrue
- например, нет проверки типа, только проверка ключа / значения.objectEquals(new Date(1234),1234)
возвращаетсяtrue
Если вы используете библиотеку JSON, вы можете закодировать каждый объект как JSON, а затем сравнить полученные строки на равенство.
ПРИМЕЧАНИЕ. Хотя этот ответ будет работать во многих случаях, как отметили несколько человек в комментариях, это проблематично по ряду причин. В большинстве случаев вы захотите найти более надежное решение.
источник
Краткая функциональная
deepEqual
реализация:Изменить : версия 2, используя предложение стрелы и функции стрелки ES6:
источник
reduce
сevery
упрощать.Object.keys(x).every(key => deepEqual(x[key], y[key]))
.: (x === y)
на: (x === y && (x != null && y != null || x.constructor === y.constructor))
Вы пытаетесь проверить, равны ли два объекта? т.е. их свойства равны?
Если это так, вы, вероятно, заметили эту ситуацию:
вам, возможно, придется сделать что-то вроде этого:
Очевидно, что эта функция могла бы сделать с небольшим количеством оптимизации и способностью делать глубокую проверку (для обработки вложенных объектов:
var a = { foo : { fu : "bar" } }
но вы поняли идею.Как указывалось в FOR, вам, возможно, придется адаптировать это для своих собственных целей, например: разные классы могут иметь разные определения «равно». Если вы просто работаете с простыми объектами, вышеприведенного может быть достаточно, в противном случае можно использовать пользовательскую
MyClass.equals()
функцию.источник
Если у вас есть удобная функция глубокого копирования, вы можете использовать следующую уловку, чтобы по- прежнему использовать
JSON.stringify
при сопоставлении порядка свойств:Демо: http://jsfiddle.net/CU3vb/3/
Обоснование:
Поскольку свойства
obj1
копируются в клон по одному, их порядок в клоне будет сохранен. А когда свойстваobj2
клонируются в клон, поскольку уже существующие свойстваobj1
просто перезаписываются, их порядки в клоне сохраняются.источник
В Node.js вы можете использовать его нативный
require("assert").deepStrictEqual
. Дополнительная информация: http://nodejs.org/api/assert.htmlНапример:
Другой пример, который возвращает
true
/false
вместо возврата ошибок:источник
Chai
имеет эту функцию тоже. В этом случае вы будете использовать:var foo = { a: 1 }; var bar = { a: 1 }; expect(foo).to.deep.equal(bar); // true;
error.name
в"AssertionError [ERR_ASSERTION]"
. В этом случае я бы заменил оператор if наif (error.code === 'ERR_ASSERTION') {
.deepStrictEqual
был способ пойти. Я ломал голову, пытаясь понять, почемуstrictEqual
не работает. Фантастический.Простейшие и логичные решения для сравнения всего, например Object, Array, String, Int ...
JSON.stringify({a: val1}) === JSON.stringify({a: val2})
Замечания:
val1
иval2
вашим объектомисточник
JSON.stringify
алфавитное переупорядочение? (Что я не могу найти документально .)Я использую эту
comparable
функцию для создания копий моих объектов, которые сопоставимы с JSON:Пригодится в тестах (большинство тестовых фреймворков имеют
is
функцию). НапримерЕсли разница обнаружена, строки записываются в журнал, что делает различия заметными:
источник
Вот решение ESES / ES2015, основанное на функциональном стиле:
демо доступно здесь
источник
Я не знаю, опубликовал ли кто-нибудь что-нибудь похожее на это, но вот функция, которую я сделал для проверки равенства объектов.
Кроме того, он рекурсивный, поэтому он также может проверять наличие глубокого равенства, если вы так его называете.
источник
Для тех из вас, кто использует NodeJS, есть удобный метод, который вызывается
isDeepStrictEqual
в нативной библиотеке Util, которая может достичь этого.https://nodejs.org/api/util.html#util_util_isdeepstrictequal_val1_val2
источник
ES6: минимальный код, который я мог бы сделать, это. Это делает глубокое сравнение рекурсивно путем строкового преобразования всех объектов, единственным ограничением является отсутствие методов или символов для сравнения.
источник
Вы можете использовать
_.isEqual(obj1, obj2)
из библиотеки underscore.js.Вот пример:
Смотрите официальную документацию здесь: http://underscorejs.org/#isEqual
источник
Предполагая, что порядок свойств в объекте не изменился.
JSON.stringify () работает для глубоких и неглубоких объектов обоих типов, не очень уверенных в аспектах производительности:
источник
Простое решение этой проблемы, которое многие не понимают, - это сортировка строк JSON (по символам). Это также обычно быстрее, чем другие решения, упомянутые здесь:
Еще одна полезная вещь в этом методе - вы можете фильтровать сравнения, передавая функцию «replacer» в функции JSON.stringify ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON / stringify # Example_of_using_replacer_parameter ). Далее будут сравниваться все ключи объектов, которые называются «сумасшедший»:
источник
areEqual({a: 'b'}, {b: 'a'})
получаетtrue
тогда?Просто хотел представить свою версию сравнения объектов, используя некоторые функции es6. Заказ не учитывается. После преобразования всех if / else в троичные я получил следующее:
источник
Мне нужна более общая функция сравнения объектов, чем была опубликована, и я подготовил следующее. Критика ценится ...
источник
Object.prototype
- в подавляющем большинстве случаев это не рекомендуется (например, добавления появляются во всех циклах for..in). Возможно посмотримObject.equals = function(aObj, bObj) {...}
?Если вы сравниваете объекты JSON, вы можете использовать https://github.com/mirek/node-rus-diff
Применение:
Если два объекта различны,
{$rename:{...}, $unset:{...}, $set:{...}}
возвращается MongoDB-совместимый объект.источник
Я столкнулся с той же проблемой и решил написать свое собственное решение. Но так как я хочу также сравнить массивы с объектами и наоборот, я создал общее решение. Я решил добавить функции в прототип, но их легко переписать в автономные функции. Вот код:
Этот алгоритм разбит на две части; Функция equals и функция для поиска числового индекса свойства в массиве / объекте. Функция find нужна только потому, что indexof находит только числа и строки, а не объекты.
Это можно назвать так:
Функция возвращает true или false, в этом случае true. Алгоритм также позволяет сравнивать очень сложные объекты:
Верхний пример вернет true, даже если свойства имеют другой порядок. Одна небольшая деталь, на которую нужно обратить внимание: этот код также проверяет наличие одного и того же типа двух переменных, поэтому «3» не совпадает с «3».
источник
Я вижу ответы кода спагетти. Без использования сторонних библиотек это очень просто.
Сначала отсортируйте два объекта по ключу, указав их ключевые имена.
Затем просто используйте строку, чтобы сравнить их.
источник
Я бы посоветовал не использовать хэширование или сериализацию (как предлагает решение JSON). Если вам нужно проверить, равны ли два объекта, вам нужно определить, что означает «равно». Может случиться так, что все элементы данных в обоих объектах совпадают, или может случиться так, что места памяти должны совпадать (имеется в виду, что обе переменные ссылаются на один и тот же объект в памяти), или может быть, что только один элемент данных в каждом объекте должен совпадать.
Недавно я разработал объект, конструктор которого создает новый идентификатор (начиная с 1 и увеличивая на 1) каждый раз, когда создается экземпляр. Этот объект имеет функцию isEqual, которая сравнивает это значение id со значением id другого объекта и возвращает true, если они совпадают.
В этом случае я определил «равно» как означающее совпадение значений идентификатора. Учитывая, что каждый экземпляр имеет уникальный идентификатор, это можно использовать для реализации идеи о том, что соответствующие объекты также занимают одно и то же место в памяти. Хотя это не обязательно.
источник
Полезно считать два объекта равными, если они имеют одинаковые значения для всех свойств и рекурсивно для всех вложенных объектов и массивов. Я также считаю следующие два объекта равными:
Аналогично, массивы могут иметь «отсутствующие» элементы и неопределенные элементы. Я бы тоже к ним относился:
Функция, которая реализует это определение равенства:
Исходный код (включая вспомогательные функции, generalType и uniqueArray): модульный тест и тестовый прогон здесь .
источник
Я делаю следующие предположения с этой функцией:
Это следует рассматривать как демонстрацию простой стратегии.
источник
Это дополнение ко всему вышесказанному, а не замена. Если вам нужно быстро сравнить мелкие объекты, не нужно проверять дополнительные рекурсивные случаи. Вот выстрел.
Это сравнивает: 1) Равенство числа собственных свойств, 2) Равенство имен ключей, 3) если bCompareValues == true, Равенство соответствующих значений свойств и их типов (тройное равенство)
источник
Для сравнения ключей для простых экземпляров объекта пары ключ / значение я использую:
После сравнения ключей достаточно простого дополнительного
for..in
цикла.Сложность - O (N * N), где N - количество ключей.
Я надеюсь / думаю, что определенные мной объекты не будут содержать более 1000 свойств ...
источник
Я знаю, что это немного устарело, но я хотел бы добавить решение, которое я придумала для этой проблемы. У меня был объект, и я хотел знать, когда изменились его данные. «что-то похожее на Object.observe» и что я сделал:
Это здесь можно продублировать и создать другой набор массивов для сравнения значений и ключей. Это очень просто, потому что они теперь являются массивами и будут возвращать false, если объекты имеют разные размеры.
источник
false
, потому что массивы не сравниваются по значению, например[1,2] != [1,2]
.