Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript - deepEqual Comparison

Question (From Eloquent Javascript 2nd Edition, Chapter 4, Exercise 4):

Write a function, deepEqual, that takes two values and returns true only if they are the same value or are objects with the same properties whose values are also equal when compared with a recursive call to deepEqual.

Test Cases:

var obj = {here: {is: "an"}, object: 2}; console.log(deepEqual(obj, obj)); // → true console.log(deepEqual(obj, {here: 1, object: 2})); // → false console.log(deepEqual(obj, {here: {is: "an"}, object: 2})); // → true 

My code:

var deepEqual = function (x, y) {   if ((typeof x == "object" && x != null) && (typeof y == "object" && y != null)) {     if (Object.keys(x).length != Object.keys(y).length)       return false;     for (var prop in x) {       if (y.hasOwnProperty(prop))         return deepEqual(x[prop], y[prop]);     /*This is most likely where my error is. The question states that all the values     should be checked via recursion; however, with the current setup, only the first     set of properties will be checked. It passes the test cases, but I would like     to solve the problem correctly!*/       }     }   else if (x !== y)     return false;   else     return true; } 

I think I have the general idea down; however, like I stated in the comment, the program will not check the second property in the objects. I feel like I have a structural/logic problem and am simply using recursion in the wrong way, as I originally intended to loop through the properties, use recursion to compare the values of the first property, then continue on in the loop to the next property and compare again. Although, I'm not sure if that's even possible?

I've given a good amount of thought and tried a couple different approaches, but this was the most correct answer I've come to so far. Any possible tips to point me in the right direction?

like image 709
Gavin Feriancek Avatar asked Aug 22 '14 21:08

Gavin Feriancek


People also ask

What is the best way to compare objects in JavaScript?

Comparing objects is easy, use === or Object.is(). This function returns true if they have the same reference and false if they do not. Again, let me stress, it is comparing the references to the objects, not the keys and values of the objects. So, from Example 3, Object.is(obj1,obj2); would return false.

Can we compare two objects in JavaScript?

In JavaScript, we cannot directly compare two objects by equality operators (double equals == or triple equals ===) to see whether they are equal or not. Comparing two objects like this results in false even if they have the same data.

How do you compare references in JavaScript?

var thesame = obj1===obj2; From the MDN : If both operands are objects, then JavaScript compares internal references which are equal when operands refer to the same object in memory.

What is == and === in JavaScript?

== is used for comparison between two variables irrespective of the datatype of variable. === is used for comparision between two variables but this will check strict type, which means it will check datatype and compare two values.


Video Answer


1 Answers

As you suspect, you're returning the match of the first property seen. You should return false if that property doesn't match, but keep looking otherwise.

Also, return false if there's no prop property found on y (that is, the counts match, but not the actual properties).

If all properties have matched, return true:

var deepEqual = function (x, y) {   if (x === y) {     return true;   }   else if ((typeof x == "object" && x != null) && (typeof y == "object" && y != null)) {     if (Object.keys(x).length != Object.keys(y).length)       return false;      for (var prop in x) {       if (y.hasOwnProperty(prop))       {           if (! deepEqual(x[prop], y[prop]))           return false;       }       else         return false;     }          return true;   }   else      return false; } 

var deepEqual = function (x, y) {   if (x === y) {     return true;   }   else if ((typeof x == "object" && x != null) && (typeof y == "object" && y != null)) {     if (Object.keys(x).length != Object.keys(y).length)       return false;      for (var prop in x) {       if (y.hasOwnProperty(prop))       {           if (! deepEqual(x[prop], y[prop]))           return false;       }       else         return false;     }      return true;   }   else      return false; }  var obj = {here: {is: "an", other: "3"}, object: 2}; console.log(deepEqual(obj, obj)); // → true console.log(deepEqual(obj, {here: 1, object: 2})); // → false console.log(deepEqual(obj, {here: {is: "an"}, object: 2})); // → false console.log(deepEqual(obj, {here: {is: "an", other: "2"}, object: 2})); // → false console.log(deepEqual(obj, {here: {is: "an", other: "3"}, object: 2})); // → true
like image 64
Paul Roub Avatar answered Oct 02 '22 10:10

Paul Roub