JSonCmp — сравниваем в JavaScript правильно

в 22:13, , рубрики: ext, Ext.js, javascript, jquery, JS library, json, Библиотека ExtJS/Sencha, метки: , , ,

Вот 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

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js