0

Teaching myself JS from various resources, including the book Eloquent Javascript. In the problem set for chapter 4, question 4 asks

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.

To find out whether to compare two things by identity (use the === operator for that) or by looking at their properties, you can use the typeof operator. If it produces "object" for both values, you should do a deep comparison. But you have to take one silly exception into account: by a historical accident, typeof null also produces "object".

I have done this, and used pythonTutor to analyze given solution and different test cases to better understand the approach. My question pertains to the variables propInA & propInB in the code below:

function deepEqual (a,b) {
if (a===b) return true;
else if (a === null || b === null || typeof a !== "object" || typeof b !== "object") return false;
else {
    let propInA = 0, propInB = 0
    for (var prop in a) {
        **propInA** +=1;
    }
    
    for (prop in b) {
        **propInB** +=1;
        
        if (!(**propInA**) || !deepEqual(a[prop], b[prop])) return false;
    
        } return **propInA** == **propInB**;
    }
}

console.log(deepEqual({here: {is: "an"}, object: 2, guy: 47}, {here: {is: "an"}, object: 2}));
// → false

As I understand it, these variables function as counters, such that when I run the test case at the bottom of this code, the additional property ("guy") in first argument causes an inequality for the number of properties between both objects, and thus deepEqual returns a false.

If this is the case, what is the function of !(propInA), in the "if..." statement where the function is called into recursion?

if (!(**propInA**) || !deepEqual(a[prop], b[prop])) return false;

Since the value of this variable is numeric, isn't it essentially asking "if 3 isn't true, then call recursive function..." ? What am I missing here?

Community
  • 1
  • 1
  • Playing around with it, and I decided to run test cases where # of properties for both objects a and b were always the same. I removed all mentions of `propInA` and `propInB` and replaced `return propInA == propInB` with `return a[prop] == b[prop]'. Feeding only test cases where a&b have same number of properties, I have not yet uncovered a way to make this code fail. What else could I do to break it? – cherish_pumpkin_boomerang Jun 24 '16 at 17:12

1 Answers1

0

In javascript a 0 is considered "falsy", so it would be saying if propInA is false, 0, undefined, null etc. In this case it's checking it's > 0.

https://developer.mozilla.org/en-US/docs/Glossary/Falsy

  • Ah. Are there any test cases that would break this? or does this + `else if (a === null || b === null || typeof a !== "object" || typeof b !== "object") return false;` effectively eliminate that possibility? – cherish_pumpkin_boomerang Jun 24 '16 at 16:52
  • Separate question: Playing around with it, and I ran test cases where # of properties for both objects a and b were always the same. I removed all mentions of `propInA` and `propInB` and replaced `return propInA == propInB` with `return a[prop] == b[prop]'. Feeding only test cases where a&b have same number of properties, I have not yet uncovered a way to make this code fail. What else could I do to break it? – cherish_pumpkin_boomerang Jun 24 '16 at 17:14
  • Saying !a is basically coverering every falsy possibility. Different properties should break it e.g. a.test vs b.hello – Andrew Wilkinson Jun 24 '16 at 17:51