Вот JavaScript-овый объект, сериализованный в JSon:
var source1 = '[{"vConfig":{"vType":"objectview","serverItemType":"TrackerObject"}}]';
А вот ещё один JavaScript-овый объект, тоже сериализованный в JSon:
var source2 = '[{"vConfig":{"serverItemType":"TrackerObject","vType":"objectview"}}]';
У них одинаковая структура, одинаковые параметры, одинаковые значения в этих параметрах. По всем признакам, и в source1
, и в source2
у нас одно и то же.
Но интерпретатор JavaScript с нами, разумеется, не согласен. И он вполне резонно считает, что source1 и source2 — разные строки. А если мы десериализуем их обратно, то получим два object-а, которые расположены по различным адресам памяти и… тоже не равны друг другу.
А если вы, впридачу, работает с Ext.js, щедро генерируете свои классы и не забываете про jSon, то может дойти до полного затмения. Как сравнить эти огромные простыни сведений о контролах, которые собираются в JSon-ы? Или разобраться древовидными объектами, где в каждое поле уже успели насоздаваться ещё какие-то подполя?
Выход один — нужно найти способ сравнивать не по значению, не по ячейке в памяти, а более гибко. Равными должны считаться те объекты, у которых одинаковые поля содержат одинаковые значения. С этой точки зрения наш source1
безусловно равен source2
.
Так и родился на свет очередной велосипед — JSonCmp. Простая, и очень нужная функция для сравнения объектов в JavaScript. Разумеется, я находил много попыток написать такую, но каждая из реализаций решала только часть проблемы — в итоге я свёл все интересные идеи в одну, попутно добавив пару своих…
Использовать его просто — достаточно подключить jsoncmp.js, и потом вызвать:
jSonCom(object1, object2);
Если объекты содержат одну и ту же информацию, функция вернёт true. Иначе — false.
Пользователи Ext.js могут использовать тот же самый алгоритм, но в обёртке плагина — jsoncmp.ext.js. Код будет выглядеть так:
Ext.ux.util.Object(object1, object2);
Правила сравнения такие:
- null равен null
- объекты разных типов не равны
- переменная по значению (Float, Integer, Boolean) сравнивается по значению
- строки сравниваются по значению
- сериализованные JSon-ы сравниваются как десериализованные объекты
- функции сравниваются по исходному коду, приведённому к string
- объекты jQuery сравниваются через стандартную для этой библиотеки функцию is
- объекты сравниваются по полям и их значениям. Если в значении поля тоже объект — он сравнивается по тому же принципу
- если при обходе этого дерева обнаруживается, что лист ссылается на один из уже пройденных объектов (это означает, что в дереве есть цикл) — будут сравниваться ссылки на объекты".
- массивы сравниваются и на соответствие элементов, и на их очерёдность
- если выставить в настройках поиска arraysAsSets = true, то массивы будут восприниматься как множества (set-ы) и очерёдность элементов будет игнорироваться. Настройки поиска выставляются в третьем, необязательном параметре. Вот таким образом:
jSonCmp([ 1, 2, 3, 4, 5 ], [ 1, 2, 3, 5, 4 ], { arraysAsSets : true })); # - true
По умолчанию arraysAsSets выставлено в false.
Я надеюсь, что это небольшая и наверняка несовершенная функция чуть-чуть, но упростит вашу работу.
Автор: RikkiMongoose