Search code examples
javascriptlogicnested-if

Even though they are logically the same, why am I getting different outputs?


It's my first time asking a question here, so I apologize if the question has been repeated earlier.

This is my official solution for freeCodeCamp JS problem:

const contacts = [
  {
    firstName: "Akira",
    lastName: "Laine",
    number: "0543236543",
    likes: ["Pizza", "Coding", "Brownie Points"],
  },
  {
    firstName: "Harry",
    lastName: "Potter",
    number: "0994372684",
    likes: ["Hogwarts", "Magic", "Hagrid"],
  },
  {
    firstName: "Sherlock",
    lastName: "Holmes",
    number: "0487345643",
    likes: ["Intriguing Cases", "Violin"],
  },
  {
    firstName: "Kristian",
    lastName: "Vos",
    number: "unknown",
    likes: ["JavaScript", "Gaming", "Foxes"],
  },
];


function lookUpProfile(name, prop) {

  for(let i = 0; i<contacts.length;i++){
    if(contacts[i].firstName == name && contacts[i].hasOwnProperty(prop)){
        return contacts[i][prop];
      }
      else {
        return "No such property"
      } 
    }
  return "No such contact";
}

console.log(lookUpProfile("Kristian", "lastName")); //Output: No such property

And this is the official solution with changes in the 'nested-if' loop:

function lookUpProfile(name, prop) {

  for(let i = 0; i<contacts.length;i++){
    if(contacts[i].firstName == name){
      if(contacts[i].hasOwnProperty(prop)){
        return contacts[i][prop];
      }
      else {
        return "No such property"
      } 
    }
  }
  return "No such contact";
}

console.log(lookUpProfile("Kristian", "lastName")); //Output: Vos

Why am I getting different solutions even if the logic behind nested-if in the official solution is similar to mine?


Solution

  • They aren't logically the same.

    Theirs is this:

    for (/*...*/) {
        if (a) {
            if (b) {
                return X;
            } else {
                return Y;
            }
        }
    }
    

    Notice that if a is not true, neither return happens, and the loop continues with the next iteration.

    But yours is:

    for (/*...*/) {
        if (a && b) {
            return X;
        } else {
            return Y;
        }
    }
    

    It returns even when a is false, never moving on to the next loop iteration.

    If you wanted to combine the outer test with the inner ones, it would be:

    for (/*...*/) {
        if (a && b) {
            return X;
        } else if (a) { // <===
            return Y;
        }
    }
    

    But that's not as clear as the original, and ends up testing a twice unnecessarily.