Profile Lookup: Why isn't this code working?

I cannot understand why my code does not work. Could someone explain it? (it says: “Bob”, “number” should return “No such contact”). I saw a lot of answers here which worked but I do not understand why this one is wrong…Thanks.

//Setup
var 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(firstName, prop){
// Only change code below this line
 
  for(var i=0; i<contacts.length; i++){
    
      if(firstName == contacts[i].firstName && contacts[i].hasOwnProperty(prop)){
        return contacts[i][prop];
      } else if (!contacts[i].firstName){
        return "No such contact";
      } else if( !contacts[i].hasOwnProperty(prop)){
        return "No such property";
      }
        
      
    }
  

// Only change code above this line
}

// Change these values to test your function
lookUpProfile("Sherlock", "lastName");

I cleaned up your code.
You need to use triple backticks to post code to the forum.
See this post for details.

Oh…didn’t know that, thanks!

1 Like

As for an explanation, the reason “No such contact” is never returned, is the else statement is never reached:

if(firstName == contacts[i].firstName && contacts[i].hasOwnProperty(prop)){
  // works semi-correctly
  return contacts[i][prop];
} else if (!contacts[i].firstName){
  //never reached
  return "No such contact";
} else if( !contacts[i].hasOwnProperty(prop)){
  // works correctly
  return "No such property";
}

Let’s look a little deeper as to your if statement logic. Whenever something like this happens, its always a good idea to debug with different test cases.

For example, try this out:

lookUpProfile("Bob", "bruh");
// ==> 'No such property'
lookUpProfile("Bob", "firstName");
// ==> undefined
lookUpProfile("Akira", "number");
// ==> '0543236543'

There is clearly an error in your if logic. Just from the previous test cases, I can see three things:

  1. A perfect search works correctly
  2. A search with an invalid firstName but valid property returns undefined
  3. A search with an invalid firstName and invalid property returns 'No such prop' instead of 'No such contact'

Ok, so what is going on here? When I do:

lookUpProfile("Bob", "bruh");

Your code does this:

if("Bob" == "Akira" && "Akira".hasOwnProperty("bruh") ){

So, in this case, it should move on to the next because Bob is not Akira and Akira does not have bruh:

else if (! "Akira")

Oops, Akira does exists. So now when we go to this:

else if( ! { firstName: 'Akira',
  lastName: 'Laine',
  number: '0543236543',
  likes: [ 'Pizza', 'Coding', 'Brownie Points' ] }.hasOwnProperty("bruh"))

!!! ERROR !!! it passes. The code sees that Akira does not have a property bruh and sends the message, but it should have stopped earlier and noticed that no object in contacts has the firstName of Bob. The code never says that Bob is not a property, because it takes the false property and checks it to Akira.

Now the next case.

lookUpProfile("Bob", "firstName");

returns undefined. Why?

if("Bob" == "Akira" && "Akira".hasOwnProperty("firstName"))

Not going to pass here. Bob does not equal Akira

else if (! "Akira")

Nope. Akira is not false. The code never sees that Bob is false either.

else if( ! { firstName: 'Akira',
  lastName: 'Laine',
  number: '0543236543',
  likes: [ 'Pizza', 'Coding', 'Brownie Points' ] }.hasOwnProperty("firstName"))

Oops. Akira does have a first name (although its driven my crazy typing it the last 20 minutes… :confounded:)
So Bob.firstName goes all the way through the tests without passing any. Thus it is returned from the function undefined because no return statement was specified outside of the else if statements.

I hope you see the errant logic. The code is close, and with a couple tweaks, maybe nesting the property check in the firstname check ;), you should get it to work. Happy Coding :smiley:

2 Likes

Thank you very much for your explanation! I looked at it now and it made sense…JS can be quite tricky…:confused:
Thank you!!

1 Like

Don’t blame JS. Any language can be tricky, especially in complex logic statements. It would not have been any easier in C#, Java, etc. The more you do it, the better you will become.

Thank you @anadebarros for your question. When I looked at this question the first time I went down exactly the same road as you! @IsaacAbrahamson thank you for your reply it was very insightful however I would like to point out a few things to clarify as I don’t feel the answer got to the crux of the matter.

Firstly I would like to point out: What we really want to use when iterating over objects in an array is a forEach loop. On some occasions a for loop is preferred however and this is such a case.
I think the most salient feature we need to realise about the forEach loop is that it is going to go over each object even once our lookUpProfile function has returned the desired result we were looking for. The for loop will not. It will break out of the loop the moment any of the conditions are met.

This raises the second point: In our example from Isaac where we run lookUpProfile(“Bob”, “bruh”) for example, it does not return undefined. It actually returns ‘no such contact’ and correctly so. So what does happen then?

The first if statement is evaluated and it is found that the firstName of the first object! This part is important… Does not match the provided Bob as provided in the arguments. It thus returns the result…and…wait for it…exits the for loop!
Nothing else happens after this point and none of the other firstName’s in the other objects are checked against the argument provided.

It is only when we nest additional conditions within each other that the loop exists at the point where we want it to as we find in the working example. We ‘solve’ the same problem with a forEach loop however we will then find we are returned all the messages for each (pun intended) of the objects including the desired result.

I hope this helps. I know the context of the problem was only with for loops but I feel it is only when considering the forEach loop and doing a comparison that one gets the deeper lesson :smiley: