Basic JavaScript - Profile Lookup

Tell us what’s happening:
No issue solving the challenge, I was able to do it in a way similar to solution 1 in the hint guide quite easily.

However, I realised that the code as-written would only work correctly if every contact had the exact same properties. If not, it would only check the first contact in the array with hasOwnProperty, see that it does, and move on.

It seemed to me that this wasn’t best practice as it wasn’t future-proofed against changes in the profile database format, so I wanted to find a way to make it work even if the contacts didn’t all have the same four properties.

After a lot of fiddling around, I got it working how I wanted! However, the code seems unnecessarily complex and clunky, and I was curious to see if anyone here can suggest a more elegant, streamlined way to solve this challenge while protecting against a situation where different profiles have different properties.

Thanks in advance for your ideas!

Your code so far

// Setup
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) {
  // Only change code below this line
  let contactProp;
  let contactName;

  for(let i=0; i<contacts.length; i++)  {
    if(contacts[i].firstName == name) {
        contactName = i
        if(contacts[i].hasOwnProperty(prop))  {
        contactProp = i;
      }  
    }
  }

  if(contactName != undefined)  {
    if(contactProp == contactName)  {
      return contacts[contactProp][prop]
    }
    else  {
      return "No such property";
    }
  }
  else  {
    return "No such contact";
  }
 
  // Only change code above this line
}

lookUpProfile("Akira", "likes");

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36

Challenge: Basic JavaScript - Profile Lookup

Link to the challenge:

Since it is a working solution to a curriculum challenge, I put [spoiler][/spoiler] tags around your code.

I don’t understand why a correct solution would only work if every contact has the same properties. The only property they “must” have for this to work is “firstName”. Everything else is optional.

And in addons like TypeScript, you would enforce what properties are allowed and required.

It seemed to me that this wasn’t best practice as it wasn’t future-proofed against changes in the profile database format,

That can be a dangerous way to think. A lot of coders get bogged down in “what if this changes” and end up spending too much time on overly complicated code trying to “future-proof” code instead of the problem that is right in front of you. Obviously there needs to be a balance - if you know a change is immanent or even likely, that might be important. But if you are working in a group and code needs to get out, I’ve seen this kind of thinking lead to work getting backed up and even accidentally create bugs or difficult to maintain code because of overly unnecessarily complex code.


const 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'
}

This is a pretty standard solution to this. It will not break if other contacts have or are missing certain props. It looks for a contact with that first name. If it does, it checks for that property. The main weakness I see of this is that it assumes that the first name is unique. But that was a given for the problem so that isn’t an issue here. In the real world, you’d use a unique id or username or have some way to deal with multiples. But this is a learning exercise and you can’t get bogged down in everything that could go wrong.

If I were coding this at work, I think a cleaner solution would be something like:

const lookUpProfile = (name, prop) => {
  const foundContact = contacts.find(contact => contact.firstName === name)
  
  if (!foundContact)
    return 'No such contact'

  return (prop in foundContact) ? foundContact[prop] : 'No such property'
}

Can you provide an example of data that you think would break this?

Hm, now that I look at it again I have no idea why I thought it wouldn’t work! I think I might have had the conditions the wrong way round, so that it was checking for hasOwnProperty before checking if the name matched. Thanks for the excellent explanation though and the very interesting sample of ‘real world’ code for this task.

After googling and reading about arrow functions, I think I understand the general idea of your code, but would you mind explaining the exclamation point in your if condition and the question mark in your return? Thanks again!

Hm, now that I look at it again I have no idea why I thought it wouldn’t work! I think I might have had the conditions the wrong way round …

Yeah, that happens sometimes. Some days, if I stare at code too long I go cross-eyed.

but would you mind explaining the exclamation point in your if condition and the question mark in your return

Sure, that is the NOT operator. It inverts the logic.

So, (!foundContact) is the same as saying “not foundContact”. In other words, if foundContact is truthy, it will be false, and if foundContact is falsy, this will be true. In other words, it is saying “if you didn’t find a contact”.

So, in other words (in practical terms):

(!foundContact) is the opposite of (foundContact)

and

(!foundContact) is the same as (foundContact != true)

Sometimes you’ll also see “!!” - that is another way to convert to a boolean, because it is a double negative.

1 Like

also,

2 Likes

Sorry, yeah, I missed that, the ternary operator.

1 Like