Another Front End Engineer Interviewing Question: Loop Alternatives

We’ve actually hired a couple of people recently, so I’m not sure if I’ll be able to bust this one out any time soon. Instead, I’ll share it with you.

This is another one that I feel works for a lot of different experience and knowledge levels. A good, junior developer should be able to give me a satisfactory answer and a senior developer could take the same problem, decide to be clever, and give me a great answer.

Let’s take a look at it.

The Markup, a Task and a Twist

I start with the following markup:

<div>div 1</div>
<div>div 2</div>
<div>div 3</div>
<div>div 4</div>
<div>div 5</div>

The task is simple. Using plain JavaScript, add a 1px border to each of those divs. The only catch is, the for loop is forbidden.

Depending on the level of the candidate, there are several answers that will bring a smile to my face.

While Loop

This is a while loop that basically takes the place of a for loop.

var divs = document.getElementsByTagName("div"),
     i = 0;
while (i < divs.length) {
    divs[i].style.border= "1px solid blue"
    i++;
}

This is a standard “right” answer for a junior developer. A junior dev who thinks of using a while loop and can actually craft one is not a phony. This is especially true now since so many people just use $(selector).each without even thinking.

This can be improved.

Faster While Loop

This isn’t much different, but it caches the divs.length to save the lookup each time.

var divs = document.getElementsByTagName("div"),
      i = 0,
  test=divs.length;
while (i < test) {
    divs[i].style.border="1px solid blue"
    i++;
}

This would be a great answer for a junior developer and a satisfactory answer for someone more senior.

With a senior developer I would ask for another alternative.

Get Wacky With a Do… While

Here’s one potential alternative. I would be surprised to get this as a primary answer, but as a secondary answer it’d be great.

var divs = document.getElementsByTagName("div"),
      i = 0,
  test=divs.length;
do {
    divs[i].style.border= "1px solid purple"
    i++;
} while (i < test)

Silver Medal- a Fast While Loop

This one indicates attention to detail and an eye towards performance.

var divs = document.getElementsByTagName("div"),
      i = divs.length;
while (i--) {
   divs[i].style.border= "1px solid   grey"
}

This reverse while loop made rounds a few years ago as the outcome of the incredible survey: What’s the Fastest Way to Code a Loop in JavaScript? Someone who either read that or had the results filter down to them is okay in my book.

The Golden Ticket

If a more senior developer busts out the below solution, they get the Gold Star.

[ ].forEach.call(divs, function(obj){obj.style.border="1px solid red"})

This shows someone who’s poked at the guts of JavaScript in a meaningful way. They also get bonus points for pointing out that forEach is slower than a for loop.

Bonus: Ignore Me For Fun and Profit

In addition to any of the above solutions, if a candidate of any level says “but really, just use CSS,” even though the instructions say “use JavaScript,” they get bonus points because, really, why do it like this?

JavaScript Ninja/Pirate/Jedi Section

Feel free to follow Adam‘s lead and propose other, interesting solutions in the comments.

10 thoughts on “Another Front End Engineer Interviewing Question: Loop Alternatives

  1. This not good enough for you?

    document.getElementsByTagName(‘body’)[0].innerHTML =
    document.getElementsByTagName(‘body’)[0].innerHTML.replace(/(<div>/g,'<div style=”border:1px solid red;”>’);

  2. The (sorta recursive) winner: http://jsfiddle.net/au2Qm/3/.

    var x = document.getElementsByTagName(‘div’);

    var els = Array.prototype.slice.call(x);
    function drawBorders(arr){
    arr[0].style.border = “1px solid red”;
    arr.shift();
    if(arr.length >= 1){
    drawBorders(arr);
    }
    }

    drawBorders(els);

  3. Your fastest solution might not actually be the fastest. I actually was doing some perf tuning for underscore.js a couple months ago for use in node and the reverse loop was 25% slower in v8 than the traditional forward loop. I re-ran the benchmark several times and it was consistent, so my hypothesis is that the forward loop tripped some fast path that reverse looping did not. This might have changed in the past couple months, but old benchmark interpreted rules of thumb do not necessarily apply to modern js engines.

    https://github.com/grayrest/underscore/wiki/Node-conversion-informal-hand-benchmark-notes

    That said, the loop construct you use doesn’t particularly matter in this case since adding a border triggers reflow in every browser (you’re modifying the box dimensions). If you cared about perf you’d copy to a document fragment first. 😉

  4. Interesting result. As I was writing this up, I was curious about how well the results still stood up since the post I referenced was a few years old. That’s a lifetime in the development of JS engines.

    I wonder what the result would be across the other engines/browsers these days.

  5. I would go with this one (is it plain javascript?):

    var arr = document.getElementsByTagName(‘head’);
    if(arr.length == 1) {
    var css = document.createElement(‘style’);
    css.type = ‘text/css’;
    css.textContent = ‘div {border:1px solid red;}’;
    arr[0].appendChild(css);
    }

  6. The task is simple. Using plain JavaScript, add a 1px border to each of those divs. The only catch is, the for loop is forbidden.

  7. The last variant will not work in IE. There aren’t any [].forEach.call in it and the result of is not an Array, but HTMLCollection so it can be accessed by [], but can’t be enumerated.

  8. Hey, this is for an interview, so the candidate only has to make these solutions work in the browser they’re doing the examples in- usually Chrome. If they mentioned that “this won’t work in browsers without a native foreach” I would simply ask them to add it to Array.prototype for extra credit.

    Secondly, it WOULD work in IE9.

    http://jsfiddle.net/2A25p/

    Also, the POINT of it is that HTMLCollections are not Arrays, but that you can borrow an Array method (forEach) to do this task.

    I would love to hear a candidate mention the following from the ES5 spec:

    NOTE The forEach function is intentionally generic; it does not require that its this value be an Array object. Therefore it can be transferred to other kinds of objects for use as a method. Whether the forEach function can be applied successfully to a host object is implementation-dependent.

Leave a Reply

Your email address will not be published. Required fields are marked *