Vincent Kipyegon

Posted on

# Detecting Changes on JavaScript Object values using Sets

Most a times in Javascript you want to know if the contents of an object literal have changed i.e when a user updates/edits their information. Most developers will simply save the information to the server without necessarily finding out if user really changed a thing or two.

Javascript sets are a collection of ordered unique values and are helpful for eliminating duplicate values. Sets are essential when dealing with discrete data.

``````let nums=[4,4,4,4,2,2,2,3,3,3]
let distinctNums=new Set(nums)

// Set(3) {4,2,3}
// convert set to Array using spread operator
nums=[...distinctNums]    // [4, 2, 3]
``````

The example above is an array with duplicate values `2` and `3` ,when you initialize a new set with the array as an argument it returns set of 7 distinct values. That’s how it works.

lets move on now; imagine, Ygritte is a beautiful single lady from Westeros North of the wall; here is a bio-data.

``````let user={name:"Ygritte",married:false,home:"North of the wall"}

``````

Then all over sudden, she meets the love of her life, Jon Snow, she gets married,relocates to Winterfell and lives happily thereafter,did they? You know nothing Jon Snow. So here is how her bio-data will look after marriage.

``````let user={name:"Ygritte Snow",married:true,home:"Winterfell"}

``````

But how will our Javascript detect that there are change of values on object literal?
Here is how we will do it

1. Convert the object values of before and after marriage of Ygritte to an iterable in this case 2 arrays using `Object.values()`
2. Merge the two arrays using spread operator
3. Create a set of merged array as well as a set of initial before object
4. Compare there sizes of before set and merged set.
``````let  before={name:"Ygritte",married:false,home:"North of the wall"}
let after={name:"Ygritte Snow",married:true,home:"Winterfell"}

let beforeArr=Object.values(before) //['Ygritte', false, 'North of the wall']
let afterArr=Object.values(after) //['Ygritte Snow', true, 'Winterfell']
let merged=[...beforeArr,...afterArr] //['Ygritte', false, 'North of the wall', 'Ygritte Snow', true, 'Winterfell']
// create sets
let mergedSet=new Set(merged)
let beforeSet=new Set(beforeArr)
if(mergedSet.size >beforeSet.size){
console.log('change detected')}
else{console.log('No change')}
``````

Whoa! I can explain what is happening here....

We merge our 2 arrays, create a merged set that will only return unique values and also create a set of before array. We then use the `size` property of Set to compare the sizes of before set (which are values of before object) and the merged set ( values of before and after objects).Typically we converted the values an object literal to an array then converted the array to a set.

If the size of `mergedSet` is bigger than `beforeSet` it means we have a new unique value on the `after object`, or simply the user info has been updated/modified.

### Caveat

Most object literals have dynamic properties that are automatically generated by the database such as `updated_at`,`created_at`, the values of these properties will give a result that the object has been updated even though it has not.

To get around them, you can either delete the dynamic object property before creating arrays or taking them into account during comparison.

``````let  before={name:"Ygritte",married:false,home:"North of the wall",created_at :"11/09/2023"}
let after={name:"Ygritte Snow",married:true,home:"Winterfell",created_at:"27/11/2023"}

delete before.created_at;
delete after.created_at;
``````