Lesson Monday

Now that you've got the basics of arrays under your belt, let's turn to a more advanced concept: Looping. Here's a very simple loop. Try it out in JSFiddle:

var languages = ['HTML', 'CSS', 'JavaScript'];
languages.forEach(function(language) {
  alert('I love ' + language + '!');
});

Let's step through how this works:

  1. Create an array of strings.
  2. Call the forEach() method on the array.
  3. Pass in a callback function to forEach, with a parameter called language.
  4. Take the first element in the array, 'HTML' and assign it to language.
  5. Pop up an alert that says you love HTML.
  6. Repeat 4 and 5 for the other elements in languages.

Adding Numbers with Loops

We can use loops for more interesting problems, too. For example, we've written code to add two numbers, but what if we wanted to add an arbitrary amount of numbers?

var total = 0;
var summands = [1, 2, 3, 4, 5];
summands.forEach(function(summand) {
  total += summand;
});
alert(total);  // 15

We create a variable named total and set it to start out at 0. Each time through the loop we will increase its value so that this variable keeps track of the running total. The first time through the loop, the variable summand becomes 1, the second time it becomes 2, and so on.

forEach loop chart

Note: It's conventional that an array name is plural, and that the parameter to the function passed into forEach() have a singular name (e.g., summands for the array and summand for the argument to the function). But for all JavaScript cares, the array could be called summands and the argument to the function could be called sofa, but that would make it slightly more difficult for other developers to pick up your code. Remember, we want to write clean, professional, easy-to-understand JavaScript.

Refactoring with Loops

Let's go back to our Mad Libs JavaScript project. One thing I didn't particularly like about our code was all the duplication:

scripts.js
$(document).ready(function() {
  $("#blanks form").submit(function(event) {
    var person1Input = $("input#person1").val()
    var person2Input = $("input#person2").val()
    var animalInput= $("input#animal").val()
    var exclamationInput = $("input#exclamation").val()
    var verbInput = $("input#verb").val()
    var nounInput = $("input#noun").val()

    $(".person1").text(person1Input);
    $(".person2").text(person2Input);
    $(".animal").text(animalInput);
    $(".exclamation").text(exclamationInput);
    $(".verb").text(verbInput);
    $(".noun").text(nounInput);

    $("#story").show();

    event.preventDefault();
  });
});

Let's refactor this using arrays and looping:

scripts.js
$(document).ready(function() {
  $("#blanks form").submit(function(event) {
    var blanks = ["person1", "person2", "animal", "exclamation", "verb", "noun"];

    blanks.forEach(function(blank) {
      var userInput = $("input#" + blank).val();
      $("." + blank).text(userInput);
    });

    $("#story").show();

    event.preventDefault();
  });
});

You might be getting tired of me pointing out the indentation, but I'm going to do it again because it's something worth taking your time to do right: Everything inside the forEach() method is indented two spaces, because it's code that's inside the callback function, and everything in a function gets indented so that it's obvious what's in the function and what's outside it.

The Importance of DRY Code ("Don't Repeat Yourself!")

I'm going to end this lesson with a short lecture. One of the best definitions of "good code" I've heard comes from Corey Haines, a developer who helps train other developers. The one thing that's certain about software, according to Corey, is that it changes. There will always be new features to add and bugs to fix. Often, the people working on the software will change, and even if they don't, the original developers will need to modify code they wrote months or years ago, code that they sometimes can't even remember writing.

One of things I really like about the new, looping version of the Madlibs JavaScript is that there's no repetition in the code, which makes it easy to change. Before, we did the same thing 6 times: get the value of the input, then put in in the appropriate blank space. If we want to change something - like, I don't know, capitalize all the text before inserting it onto the page (obviously this is contrived, but hopefully you get the idea) - then we have to change all 6 places. In this small example, the only room for error is maybe forgetting to update one line, although that would be embarrassing. But as your programs get more complex, you'll see that, if you have repetitive code, it becomes very difficult to maintain, and you will regularly update one place and fail to update another - or worse yet, update them in different ways that cause incompatibilities down the road.

There's a principle in software development called Don't Repeat Yourself, or DRY. DRY code is easy to change, because you only have to make any change in one place. One way we DRY up our code is by taking repetitive bits of code and extracting them into a function. Another way is by taking something we do several times and by turning it into a loop. Whenever you finish writing some code, you should always look back to see if there is any way you can DRY it up.

Also, remember how I harped on about using descriptive variable names? "Easy to change" doesn't just mean clean code - if you can't figure out what a variable is for or what a function does based on its name, then it's harder to change it down the road, when you might not remember exactly how your code works (or when somebody else is trying to change your code).

Terminology


  • Looping: The act of repeating the same block of code until it is specified to stop. For example, the forEach() loops used in this exercise repeat the same block of code for each element of an array. When it completes cycling through all elements of the array, it stops.

  • DRY Code: DRY stands for "Don't repeat yourself!" and refers to code that is well-refactored and efficient, instead of redundant. DRY code has many benefits, including being easier for other developers to pick up, being easier to maintain and update, and easier to debug when issues occur.

Examples


Simple loop using forEach():

languages.forEach(function(language) {
  alert('I love ' + language + '!');
});

More advanced loop to add numbers:

var total = 0;
summands = [1, 2, 3, 4, 5];
summands.forEach(function(summand) {
  total += summand;
});

Manipulating DOM elements with jQuery in a loop:

var classes = ["some-class", "some-other-class", "another-class"];
classes.forEach(function(class) {
  $("." + class).hide();
});

Tips


When choosing a name for the variables in your loop, remember that it is good practice to use a plural for the array and the singular form of that word for the loop.

> var languages = ['HTML', 'CSS', 'JavaScript'];
> languages.forEach(function(language) {
    alert('I love ' + language + '!');
  });

The array is named languages and the parameter is the singular language.