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