I'm learning JavaScript and trying to do this exercise:
Write a function
deepEqual
that takes two values and returnstrue
only if they are the same value or are objects with the same properties, where the values of the properties are equal when compared with a recursive call todeepEqual
.To find out whether values should be compared directly (use the
===
operator for that) or have their properties compared, you can use thetypeof
operator. If it produces "object" for both values, you should do a deep comparison. But you have to take one silly exception into account: because of a historical accident,typeof null
also produces "object".The
Object.keys
function will be useful when you need to go over the properties of objects to compare them.
This is my solution and gives me true
, false
, false
which is wrong
function deepEqual (a,b) {
if (a===b) return true;
if (typeof a=="object" && typeof b=="object") {
let x=Object.keys(a), y=Object.keys(b);
if (x.lenght==y.lenght) {
for (key of x){
if (y.includes(key)){
if (a[key]===b[key]) return true;
else return false;
}
}
}
return true;
}
}
let obj = {here: {is: "an"}, object: 2};
console.log(deepEqual(obj, obj));
console.log(deepEqual(obj, {here: 1, object: 2}));
console.log(deepEqual(obj, {here: {is: "an"}, object: 2}));
This is the right solution:
function deepEqual(a, b) {
if (a === b) return true;
if (a == null || typeof a != "object" ||
b == null || typeof b != "object") return false;
let keysA = Object.keys(a), keysB = Object.keys(b);
if (keysA.length != keysB.length) return false;
for (let key of keysA) {
if (!keysB.includes(key) || !deepEqual(a[key], b[key])) return false;
}
return true;
}
let 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
I can't really understand what's wrong with what I wrote and how can I fix it.
Thank you very much for helping a noobie :)
Here are the issues in your code:
1) The test for objects:
if (typeof a=="object" && typeof b=="object") {
This is fine, but what if this condition is not true? You don't have any code that deals with that case, so the function will return undefined
. It should return false
instead.
Secondly, there is this weird thing in JavaScript about which the question has warned you -- you should have taken it into account:
...because of a historical accident,
typeof null
also produces "object".
...so you need to have a separate test for that, as null
is not really an object and code will produce errors when you treat it as one.
In your code a null
value would pass this if
test and would then execute Object.keys(null)
, which triggers an exception. A null
value should not be allowed in there.
2) Comparing the number of properties
if (x.lenght==y.lenght) {
There is a spelling mistake. It is not lenght
, but length
(2x). And again, what if this condition is not true? There is no code that deals with that case, except for the return true
after that if
block, yet your function should then return false
.
3) Check that a property exists in both objects
if (y.includes(key)){
This test works, but is not optimal. includes
is slower than just checking that key in b
(it is a pity that the reference solution also uses includes
).
And as before, what if this condition is not true? The function should immediately exit the loop and return false
, but this is not happening...
4) Check that the values for the same properties are deep equal.
if (a[key]===b[key]) return true;
This condition does not do a deep comparison. The question already told you what to do here:
...where the values of the properties are equal when compared with a recursive call to
deepEqual
So here is that occasion where you should perform a recursive call, so any nested objects are compared in the same way. Just a[key]===b[key]
will be false
when these two values are separate objects. But the condition should really be true
when those objects have the same properties, and same values for them... which is exactly what your function is able to do: so call it here.
Secondly, this is not the time to return true
, as this will exit the loop without checking also the other keys, and there the outcome could be negative... And one "negative" is enough to make the overall end result false
. So while things are good, you should continue the loop.
5) When the values are different
else return false;
Yes, this is the right time to return false
.
6) When all tests succeeded
return true;
This is the only right place to return true
, but you should solve the second remark in my answer so this statement is not executed when the lengths are different.
As you already have correct code to compare with, it is a bit overkill to repeat that code here.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.