Lesson Weekend

We can now add a Contact to our AddressBook, but what if we later need to find a specific contact? This is a pretty standard feature in any electronic address book, so let's include it in ours too! We'll create a find() method that allows us to find a Contact by its id property.

Finding Contacts

Let's write this method now, right below assignId(). It will be a AddressBook prototype because that's where we're trying to find the specific Contact:

scripts.js
...

AddressBook.prototype.findContact = function(id) {
  for (var i=0; i< this.contacts.length; i++) {
      if (this.contacts[i].id == id) {
        return this.contacts[i];
      }
    };
  return false;
}

...
  • Notice it takes an id as an argument. This will contain the unique ID we assigned to each Contact in the previous lesson.

  • The method then loops through the AddressBook object's contacts array, checking each entry's id against the id provided to the findContact() method as an argument.

  • When a match is found, the method returns the Contact object with that specific id.

Also, notice we use a for loop instead of a forEach. This is because we can return from (or 'break out' of) a for loop. We can't escape from a forEach loop. We want to stop looping as soon as we find a matching id. It wouldn't be efficient if the loop continued even after finding a match, especially if there were a million records! If there's a Contact with a matching id, it returns the Contact. If there isn't, it returns false because there's no match.

Testing it Out

Let's test our new method out. Like before, we'll copy/paste the contents of scripts.js into the browser's JavaScript console, then enter the following to populate our AddressBook:

var addressBook = new AddressBook();
var contact = new Contact("Ada", "Lovelace", "503-555-0100");
var contact2 = new Contact("Grace", "Hopper", "503-555-0199");
addressBook.addContact(contact);
addressBook.addContact(contact2);

Then we'll confirm our code provided each Contact an id by entering the following:

contact2;

The console will respond with the Contact object that corresponds to the variable contact2:

Contact {firstName: "Grace", lastName: "Hopper", phoneNumber: "503-555-0199", id: 2}

Notice it contains an id, even though we didn't give the constructor one as an argument. This is because addContact() now calls our assignId() property automatically.

Now we can test our new findContact() method by providing it this Contact's' id and confirming it returns the correct info:

addressBook.findContact(2);

It will return the following:

Contact {firstName: "Grace", lastName: "Hopper", phoneNumber: "503-555-0199", id: 2}

Great! findContact() can successfully locate a Contact using the corresponding id!

Deleting Contacts

Let's add one more method for practice. What if we wanted to delete a Contact from our AddressBook? Here's a method to do that. We'll add it right below findContact():

scripts.js
...

AddressBook.prototype.deleteContact = function(id) {
  for (var i=0; i< this.contacts.length; i++) {
    if (this.contacts[i].id == id) {
      delete this.contacts[i];
      return true;
    }
  };
  return false;
}

...

It's very similar to findContact(). However, it deletes the contact with a matching ID and then returns true because the operation was completed. (If there's no record with a matching id to delete, it returns false.)

But there's one problem: the delete method will leave gaps in the array, breaking our findContact() method! (You can test this out in the console; now that some elements in the contacts array are empty, or undefined, they won't have an id property.)

Let's update findContact() to handle this:

scripts.js
...

AddressBook.prototype.findContact = function(id) {
  for (var i=0; i< this.contacts.length; i++) {
    if (this.contacts[i]) {     // <-- This line is new!
      if (this.contacts[i].id == id) {
        return this.contacts[i];
      }
    }                          // <-- This line is also new!
  };
  return false;
}

...

This time we only check an array element's id property if that element is a Contact. We'll also need to update the deleteContact() method in the same way:

scripts.js
...

AddressBook.prototype.deleteContact = function(id) {
  for (var i=0; i< this.contacts.length; i++) {
    if (this.contacts[i]) {     // <-- This line is new!
      if (this.contacts[i].id == id) {
        delete this.contacts[i];
        return true;
      }
    }                          // <-- This line is also new!
  };
  return false;
}

...

After following along with this lesson, our entire scripts.js file will look like this:

scripts.js
// Business Logic for AddressBook ---------
function AddressBook() {
  this.contacts = [],
  this.currentId = 0
}

AddressBook.prototype.addContact = function(contact) {
  contact.id = this.assignId();
  this.contacts.push(contact);
}

AddressBook.prototype.assignId = function() {
  this.currentId += 1;
  return this.currentId;
}

AddressBook.prototype.findContact = function(id) {
  for (var i=0; i< this.contacts.length; i++) {
    if (this.contacts[i]) {
      if (this.contacts[i].id == id) {
        return this.contacts[i];
      }
    }
  };
  return false;
}

AddressBook.prototype.deleteContact = function(id) {
  for (var i=0; i< this.contacts.length; i++) {
    if (this.contacts[i]) {
      if (this.contacts[i].id == id) {
        delete this.contacts[i];
        return true;
      }
    }
  };
  return false;
}

// Business Logic for Contacts ---------
function Contact(firstName, lastName, phoneNumber) {
  this.firstName = firstName,
  this.lastName = lastName,
  this.phoneNumber = phoneNumber
}

Contact.prototype.fullName = function() {
  return this.firstName + " " + this.lastName;
}

You can also experiment with adding other methods as well. For instance, try adding an update() method on the Contact prototype. The main focus this week is constructors and prototype methods, so we encourage you to focus on this. When working with business logic, make sure to test it in the console before incorporating it into your UI logic.


Example GitHub Repo for the Address Book

Examples


Find a Contact:

AddressBook.prototype.findContact = function(id) {
  for (var i=0; i< this.contacts.length; i++) {
    if (this.contacts[i]) {
      if (this.contacts[i].id == id) {
        return this.contacts[i];
      }
    }
  };
  return false;
}

Delete a Contact:

AddressBook.prototype.deleteContact = function(id) {
  for (var i=0; i< this.contacts.length; i++) {
    if (this.contacts[i].id == id) {
      delete this.contacts[i];
      return true;
    }
  };
  return false;
}

Example GitHub Repo for the Address Book