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?
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.
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.
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.
== 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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With