Paradigms of Iteration in JavaScript

  Kris Jordan        2012-01-08 10:11:15       4,538        0    

One of the joys of programming is that no matter how simple a problem may seem there are always tons of ways to solve it. It can be good practice to go back and revisit fundamentals by solving simple problems with as many implementations as you can think of. In this post we'll explore approaches to basic iteration in JavaScript.

This style of exercise is a good interviewing technique, too, because it's open ended and leads to good discussions. The focus isn't a tricky, wacky problem you're seeing for the first time ever, but bread and butter programming awareness, command, and comfort. It's a good warmup to get a sense of strengths and depth of knowledge.

A Basic JavaScript Iteration Problem

Iterate through an array of letters, in order, one-at-a-time, and print them using console.print. Here are your letters.

1
var letters = [ 'a', 'b', 'c' ];

Your solutions should achieve the equivalent of the following hard-coded, brute force solution, except they should handle arrays of any length.

1
2
3
console.log(letters[0]);
console.log(letters[1]);
console.log(letters[2]);

How many different solutions can you come up with? Loop constructs, functions, library functions, you can use any means possible.

Go on, pop open your developer console. Play around.

Did you cover the loop constructs (for, while, do..while, for..in)?

Did you write an enumeration object?

What library functions are in your tool belt (Array.[forEach][mdc-for-each], jQuery.[each][jquery-each], underscore.[each][underscore-each],...)?

Did you roll your own naive each function?

Did you implement your each function recursively, without using a loop construct at all?

Did you do something mind blowing not even mentioned? Awesome, leave a comment!

Iterative Solutions

When learning a language like Java, C, or JavaScript, one of the first things we're often taught are language-defined looping constructs. With JavaScript's functional capabilities it's possible to avoid using looping constructs almost altogether. We're talking fundamentals, here, though, and it's important to be comfortable with each basic construct. Let's take a look at a while loop based solution.

1
2
3
4
5
var i = 0;
while( i < letters.length) {
    console.log(letters[i]);
    i++;
}

How would you transform that while loop to a for loop? Why is a do..while loop awkward to use here? What risk does for..in pose looping through an Array object?

Functional Solutions

JavaScript's treatment of functions as first-class values enables us to avoid writing loop constructs in a wide variety of situations. Resig's jQuery can largely be thanked for encouraging this style of iteration throughout the web development community. Let's solve the problem with jQuery's [each][jquery-each] function.

1
2
3
$.each( letters, function(i) { console.log(letters[i]); } );
// or
$.each( letters, function(i, letter) { console.log(letter); } );

jQuery's each expects a callback with a signature of (index,value). This is a different signature than ECMAScript's Array.forEach function which has the inverse and provides a reference to the array as the third argument (value,index,array).

1
2
3
letters.forEach( function(letter) { console.log(letter) } );
// or
['a','b','c'].forEach( function(letter, i, letters) { console.log(letters[i]); });

These iteration functions are nice. Have you implemented one before? If you wrote a for loop you can do it.

Let's implement a naive equivalent that passes just each element's value to the user-defined function.

1
2
3
4
5
6
var each = function( array, fn ) {
    for( var i = 0; i < array.length; i++) {
        fn(array[i]);
    }
};
each( letters, function(letter) { console.log(letter); } );

We've come up with a "functional" solution by abstracting away an iterative solution. A truly functional solution shouldn't need a loop at all. Functions only!

Recursive Solutions

If we can't use a loop construct we'll need to "jump" back to the top of our iteration by invoking a function recursively. Like a loop we'll need a base case an a recursive case. When will we exit and move back down the stack? Here's one take:

1
2
3
4
5
6
7
8
var each = function( array, fn, i ) {
    if(i === undefined) { i = 0; }
    if(i < array.length) {
        fn(array[i]);
        each(array, fn, i+1);
    }
}
each( letters, function(letter) { console.log(letter); } );

Look ma, no loops!

Object-Oriented Style Enumeration Solutions

Enumeration/iteration objects are a commonly used pattern in object-oriented programming. This style isn't frequently used in JavaScript, but it's interesting enough to deserve a mention.

Iteration state, in this problem the index in the array, as well as the logic for traversal, in this case incrementing the array from 0 to the end of the array, are both encapsulated within the iterator object.

1
2
3
4
5
6
7
8
9
10
11
12
var iterator = {
    i:       0,
    hasNext: function() {
        return iterator.i < letters.length;
    }
    next:   function() {
        return letters[iterator.i++];
    }
};
while( iterator.hasNext() ) {
    console.log(iterator.next());
}

What is interesting about this approach is you can use different traversal orders without actually changing the logic of any loops that depend on the iterator object. Can you write a reverseIterator? Can you write an each to take an iterator object rather than a plain old array? What is interesting about the functional style, about the object-oriented style, about the intersection of the two?

Wrap up

It's good for everyone to get back to the fundamentals every now and then and practice technique. Even trivial programming problems, like printing an array of letters, have non-trivial solutions. Exploring solution spaces can cover a lot of ground and act as a great tool for identifying strengths and discomforts.

What other solutions did you come up with?

Source : http://www.newmediacampaigns.com/blog/paradigms-of-iteration-in-javascript

JAVASCRIPT  ITERATION  WRAP  RECURSIVE  FOR  LOOP 

       

  RELATED


  0 COMMENT


No comment for this article.



  RANDOM FUN

TCP vs UDP