1

I am trying to find out if there any any es6 (or external library) ways to handle deep object comparison and parsing in JavaScript.

Take the following example, where I have a property history, which is an array, embedded within a property services, which is also an array:

 {
   _id: 4d39fe8b23dac43194a7f571,
   name: {
     first: "Jane",
     last: "Smith"
   }
   services: [
    {
     service: "typeOne",
     history: [ 
       { _id: 121, 
         completed: true,
         title: "rookie"
       },
       { _id: 122, 
         completed: false,
         title: "novice"
       } 
      ]
     },
     {
      service: "typeTwo",
      history: [ 
       { _id: 135, 
         completed: true,
         title: "rookie"
       },
       { _id: 136, 
         completed: false,
         title: "novice"
       } 
      ]
     }
   ]
 }

Now, say a new element is pushed onto the "history" array within the second "services" element, where (service : "typeTwo") -- on the "services" array. I need to identify that's happened, and pull out the entire parent element, because I also need to know what "service" within the "services" array had a new "history" element added.

Is there a way I can scan this entire object and not only determine when something's changed, but actually be able to pull out the section I need reference to? I'm open to either a native JS or JS library option here.

Muirik
  • 6,049
  • 7
  • 58
  • 116
  • [diff](https://github.com/flitbit/diff) is one. IIRC this gives you the path of the edit which should help in your case. – nicholaswmin Feb 08 '19 at 21:21
  • Possible duplicate of [Generic deep diff between two objects](https://stackoverflow.com/questions/8572826/generic-deep-diff-between-two-objects) – Heretic Monkey Feb 08 '19 at 21:25
  • You want to make your nested array *reactive*? As in, when the array is updated, you want a callback to trigger and get the parent data? – adiga Feb 08 '19 at 21:30
  • @Muirik Are you trying to observe asynchronous mutation of a JavaScript object? _"I need to identify that's happened"_? How is an element pushed to the array? – guest271314 Feb 08 '19 at 21:38
  • I think you need to look into RxJs and do some reactive programming rather that watching for updates. RxJs takes a bit to get your head around but will change the way you develop applications. It is a complete game changer. – Adrian Brand Feb 08 '19 at 23:08
  • @guest271314, because I'm utilizing `pre` and `post` hooks in a Node/MongoDB backend application, I'm guaranteed to get access to the two states of the document. So that's not the problem. The problem is in being able to access deep, nested layers of the document when comparing the two documents (i.e. the two states of the same document to see what's changed). – Muirik Feb 09 '19 at 15:40
  • @Muirik What is the expected output? The index of the array that is different? – guest271314 Feb 09 '19 at 16:39
  • @guest271314, let's say that after the save the document now has 3 elements in the "history" array, rather than 2. What I'd like to be able to do is compare the two documents and pull out element within "services" that changed. That way I know which "service" within "services" changed, and I know the specifics of the new element added to the "history" array within that "service". – Muirik Feb 11 '19 at 13:04
  • @Muirik How are elements added to the array? – guest271314 Feb 11 '19 at 14:21
  • Have you looked at [lodash](https://lodash.com/docs/4.17.15#isEqual) _.isEqual which does a performs a deep comparison? – Samuel Goldenbaum Nov 15 '19 at 04:30

2 Answers2

0

You can check for duplicates like this:

function isEqual(firstObject, secondObject) {
  function _equals(firstObject, secondObject) {
    let clone = {...{}, ...firstObject}, cloneStr = JSON.stringify(clone);
    return cloneStr === JSON.stringify({...clone, ...secondObject});
  }
  return _equals(firstObject, secondObject) && _equals(secondObject, firstObject);
}

https://jsfiddle.net/b1puL04w/

0

If you considering libraries has stated, then lodash has _.isEqual which does perform a deep comparison between two values to determine if they are equal.

I have used it extensively for deep comparison in the past.

Samuel Goldenbaum
  • 18,391
  • 17
  • 66
  • 104