panzerdp / dmitripavlutin.com-comments

7 stars 0 forks source link

/how-to-compare-objects-in-javascript/ #72

Open panzerdp opened 4 years ago

panzerdp commented 4 years ago

Written on 06/07/2020 14:05:08

URL: https://dmitripavlutin.com/how-to-compare-objects-in-javascript/

panzerdp commented 4 years ago

Comment written by Alon Valadji on 06/09/2020 21:59:28

JSON.stringify(object1) === JSON.stringify(object2) won't work with circular objects.

However, you can use JSON.stringify replace function to hash the circular object and gain a full deep comparison.

see how cycle.js does it:
https://github.com/douglasc...

TypeError: cyclic object value on MDN:
https://developer.mozilla.o...

panzerdp commented 4 years ago

Comment written by Dmitri Pavlutin on 06/10/2020 06:55:47

Good to know. Thanks for sharing @alonronin:disqus.

panzerdp commented 4 years ago

Comment written by Federico Kereki on 06/12/2020 17:39:25

Another problem with JSON.stringify:

obj1 = {a:2, b:4};
obj2 = {b:4, a:2};
JSON.stringify(obj1); // "{"a":2,"b":4}"
JSON.stringify(obj2); // "{"b":4,"a":2}"

panzerdp commented 4 years ago

Comment written by veganaiZe on 06/12/2020 22:06:11

JSON.stringify() doesn't include methods.

panzerdp commented 4 years ago

Comment written by Dmitri Pavlutin on 06/13/2020 09:20:15

Exactly. JSON.stringify preserves properties order, which makes it error-prone to compare objects.

panzerdp commented 4 years ago

Comment written by Nicholas Tapia on 06/13/2020 17:26:10

I love reading about your reasoning and thought process. I really helps me as a novice programmer to understand! Two questions:

1) You recommend:
isDeepStrictEqual(object1, object2) or _.isEqual(object1, object2)
Why do you recommend them?

2) What are some real world examples of when one would need to do referential equality on objects?

panzerdp commented 4 years ago

Comment written by Dmitri Pavlutin on 06/13/2020 18:13:34

Hi @disqus_vqzZeHeESm:disqus ,

1) Why do you recommend them?

If you're writing a Node application, it's better to use the built-in Node modules/functions. This way you don't have to write the functions by yourself, or add another dependency if you choose to use a utility library from npm.

2) What are some real world examples of when one would need to do referential equality on objects?

For example, if you'd like to store some information related to an object, but not on the object itself. You could store the data into an array having tuples of object and related data: [[object1, relatedData2], [object2, relatedData2], ...]. Then to access the related data of an object, you could iterate the array and use the object referential equality to find the match.

panzerdp commented 4 years ago

Comment written by Nicholas Tapia on 06/13/2020 23:26:54

Very helpful! Thank you kindly!

panzerdp commented 4 years ago

Comment written by Rayan Noe on 06/15/2020 11:38:54

use
```
const propertyName = keys1[index];
const val1 = object1[propertyName];
const val2 = object2[propertyName];
```
instead
```
const val1 = object1[keys1[index]];
const val2 = object2[keys2[index]];
```

otherwise it will return true if the property name is different in same position and value is equal.
eg :
deepEqual({ "name1" : "abc" } , { "name2" : "abc" });

panzerdp commented 4 years ago

Comment written by Dmitri Pavlutin on 06/15/2020 12:14:52

You're right. I will fix the functions.

panzerdp commented 4 years ago

Comment written by jay on 07/21/2020 03:55:06

JSON.stringify is fine for smaller objects. There is still a limitation for the size of string that can be compared in JavaScript.

panzerdp commented 4 years ago

Comment written by Дмитрий on 09/17/2020 04:33:50

Thnx, Dima, so clear!

vevan commented 4 years ago
const hero1 = {
  name: 'Batman',
  realName: 'Bruce Wayne'
};
const hero2 = {
  name: 'Batman',
  realName: 'Bruce Wayne'
};
const hero3 = {
  name: 'Joker'
};

function cpObj(obj1,obj2){
    const tmp = {...obj1,...obj2}
    return JSON.stringify(obj1) === JSON.stringify(tmp)
}

cpObj(hero1,hero2)
talHaram commented 3 years ago

Hi Dima. Great job. small improvs - if I may - to use this function to all sort of objects. Here is my function code. I has many recursive calls...

export const objectsCompare = (obj1,obj2) => { const primitive = ['string','number','boolean','undefined']; const typeA = typeof obj1; const typeB = typeof obj2; if (typeA!==typeB) {return false}; if (primitive.includes(typeA)) {return obj1===obj2} //if got here - objects if (obj1.length!==obj2.length) {return false} //check if arrays const isArrayA = Array.isArray(obj1); const isArrayB = Array.isArray(obj2); if (isArrayA !== isArrayB) {return false} if (isArrayA) { //arrays for (let i = 0; i < obj1.length; i++) { if (!objectsCompare(obj1[i],obj2[i])) {return false} } } else { //objects //compare object keys if (!objectsCompare(Object.keys(obj1).sort(),Object.keys(obj2).sort())) {return false} //compare object values let result=true; Object.keys(obj1).forEach((key)=>{ if (!objectsCompare(obj1[key],obj2[key])) {result=false} }) return result } return true }

panzerdp commented 3 years ago

Hi Dima. Great job. small improvs - if I may - to use this function to all sort of objects. Here is my function code. I has many recursive calls...

Thanks for sharing your implementation @talHaram.

Gleb-Gaiduk commented 3 years ago

Great blog starting from the content ending with the text structure, fonts and design.

tmillr commented 3 years ago

A better shallow comp!

function shallowEqual(object1, object2) {
    const keys1 = Object.keys(object1);
    const keys2 = Object.keys(object2);

    // cannot simply compare key-array lengths as lengths could be same while the keys themselves differ
    // cannot skip this check either and just check the values of all keys concatenated
    // because { "key": undefined }["key"] and {}["key"] would equal incorrectly
    for (const k of keys1) if (!keys2.includes(k)) return false;
    for (const k of keys2) if (!keys1.includes(k)) return false;

    for (const key of keys1) if (object1[key] !== object2[key]) return false;

    return true;
}
Chayanonjackal commented 3 years ago

thx :)

nzolotar commented 2 years ago

Great overview. thank you for nice, clean and short explanation. Enjoyed!

panzerdp commented 2 years ago

Great overview. thank you for nice, clean and short explanation. Enjoyed!

Glad you like it @nzolotar!