News for hackers. Stuff that matters.
Re:JavaScript Interview Question by raganwald on Thursday January 20, 2011 @01:48PM (#2124758)
This is a bit of a "gotcha" question.

I have absolutely no faith that someone in an interview who doesn't figure out the scoping issue in the interview doesn't understand Javascript scopes. In the "real world" of a job, the problem is presented like this: "This code exhibits the following behaviour: It outputs a four every time instead of one, two, three, and four Find out why and fix it, please."

Given as a gotcha, I would stare at the code, and possibly figure out the scope issue. Then I would keep staring. Is this the only "gotcha," or has the interviewer diabolically inserted two bugs and I have to find the second one?

The entire process would make me feel like I was in an adversarial position, where the interviewer is trying to point his finger at me and yell "FAIL! I pwn3d you with my l33t Javascript questioning skillz!!"

FWIW, I think I understand the solution. In fact, I wrote a blog post about the exact same thing:

https://github.com/raganwald/homoiconic/blob/master/2010/10/...

But nevertheless, I know that from time to time I unwittingly make this mistake when coding and quickly fix it. I don't have a lot of confidence I would be guaranteed to get the correct answer in an interview every time.

Which is maybe why I don't like it as an interview question: Perhaps I'm not smart enough to get the answer right every time. Perhaps the only questions I like are the ones I like to be asked :-)

Re:JavaScript Interview Question by dmvaldman on Thursday January 20, 2011 @12:43PM (#2124448)
Spoiler Alert!

each list item alerts 4 when clicked. This has to do with closures in js. The way I understood it (and please correct if inaccurate) is that each list item has an event listener that calls function: alert(i). However, it's not true that each list item has its own value for i. The value of i is figured out only when the link is clicked.

Once script finishes, i has the value 4, and when clicked on, each list item draws from this value of i instead of the one in which it is originally assigned.

Re:JavaScript Interview Question by bcrescimanno on Thursday January 20, 2011 @12:49PM (#2124486)
"The value of i is figured out only when the link is clicked."

This makes it sound a bit like magic. A more accurate description is that the usage of the variable "i" within the closure is simply a reference to i in the outer function--not a copy of the value.

A great follow-up is to describe the memory implications of what they've done here and how memory use can be improved.

Re:JavaScript Interview Question by dmvaldman on Thursday January 20, 2011 @01:08PM (#2124580)
ahh thank you this makes more sense. If I understand you correctly...

- each list item has a pointer to a function: alert(i) (functions are first class objects)

- the value of i is determined from the outer function (which is in some unraveled way the for(i=0; i<els.length; i++)) because it is within the scope of the above function

-link item executes alert(i) with i = 4, when clicked.

Re:JavaScript Interview Question by broquaint on Thursday January 20, 2011 @12:55PM (#2124521)
The behaviour is due to the fact that variables in JavaScript are scoped to the function, although as that code is in the global scope and lacks a var declaration it will live under the global object (window in this case). So in that example each closure captures the same variable hence 4 being produced within each alert(). For more info see: https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/C...
Re:JavaScript Interview Question by Xavi on Thursday January 20, 2011 @12:30PM (#2124383)
A while back a couple of colleagues sat down and came up with our own set of JS interview questions. Here's what we came up with:

Can the interviewee code: https://gist.github.com/633341

Can the interviewee read/debug code: https://gist.github.com/633087

I used these questions during a couple of interviews. They seemed to work well.

Re:JavaScript Interview Question by pdelgallego on Thursday January 20, 2011 @01:29PM (#2124668)
What its the percentage of developers that pass the questions?

I don't think many entry level programmers will think about returning a function to implement say, but I can be wrong.

Re:JavaScript Interview Question by Xavi on Thursday January 20, 2011 @02:05PM (#2124847)
Many interviewees, when presented with `say("hello")("world")`, understood that `say` was a function that returned a function, but few were able to actually implement `say`.
Re:JavaScript Interview Question by erikwiffin on Thursday January 20, 2011 @02:27PM (#2124912)
I like this question, and I've got something that works, but I'm not sure it's the prefered solution.

  function say(arg) {
    return function(word) {
      alert(arg + " " + word);
    };
  }
It solves "hello world", but wouldn't work for something like say("dogs")("and")("cats"). Are you expecting an arbitrary number of function returns?
Re:JavaScript Interview Question by Xavi on Thursday January 20, 2011 @03:22PM (#2125121)
Yep, that is exactly the solution I would be looking for.

I would be blown a way if someone came up with solution that could handle arbitrary function returns. My friend actually wrote an interesting article on the subject. Here's the link if you're interested: http://msdn.microsoft.com/en-US/scriptjunkie/gg575560.aspx

Re:JavaScript Interview Question by jaysoo on Thursday January 20, 2011 @05:23PM (#2125558)
Not exactly the same signature, but can handle arbitrary number of calls.

var say = (function() {

    var savedArgs = [];

    return (function recurse () {

        if (arguments.length) {

            for (var i=0, arg; arg=arguments[i]; i++) {

                savedArgs.push(arg);

            }

            return recurse;

        } else {

            alert(savedArgs.join(' '));

            savedArgs = [];

        }

    });
})();

// e.g. say('Hello')('World')('!!')();

// --> alerts "Hello World !!"

Re:JavaScript Interview Question by sibsibsib on Friday January 21, 2011 @03:05PM (#2128663)
here's the version I came up with, based on one I did in python. It's very similar to jaysoo's - needs a call with no args to terminate the list. I'm curious if there's a way to do this somehow without the terminator.

I'm not a JS expert by any means, so if I'm doing something stupid in this code, I'd love to know.

  var say = function(word) {
    
    words = [word];

    func = function(word2) {
        if (word2) {
            words.push(word2);
            return func;
        }
        else {
            print(words.join(' '));
        }
    }

    return func;
  };
say('hello')('bob')('how you doing?')();

*note I have the function 'print' aliased to console.log for convenience.

Re:JavaScript Interview Question by noblethrasher on Thursday January 20, 2011 @03:14PM (#2125096)
According to the expected output, you'd need something like:

    function say(x)
    {
    	return function (y) { alert( capitalize(x) + " " + capitalize(y)); }
    }
Where capitalize makes the first character uppercase.
Re:JavaScript Interview Question by Xavi on Thursday January 20, 2011 @03:24PM (#2125127)
Oops, that's a type-o. The capitalize doesn't need to change.

Thanks for the heads up.

Re:JavaScript Interview Question by theoretical on Thursday January 20, 2011 @01:26PM (#2124652)
They seem like good questions. As an addendum to the final question in second link, it might also be worthwhile checking the interviewee's understanding of "this" in other contexts too.
Re:JavaScript Interview Question by smysore on Thursday January 20, 2011 @12:57PM (#2124530)
is it silly of me to think that this doesn't seem hard enough to be an interview question? i'd be more interested in whether (and how quickly) someone could grasp a complex problem
Re:JavaScript Interview Question by bcrescimanno on Thursday January 20, 2011 @01:29PM (#2124671)
When hiring front-end developers, there's a lot of people out there who fall into the "web designer guy who learned some coding along the way." They aren't engineers--and while they likely could study and learn, they really haven't. To me this is a really simple screening question; an engineer who understands closures, scope, and variable references will immediately say, "yeah, I see what's happening here..." and answer correctly.

Having conducted likely close to a hundred UI Engineer interviews, definitely over a hundred phone screens, and seen what feels like thousands of resumes (probably hyperbole on that last one), I can assure you that many candidates I've seen couldn't answer this question.

Re:JavaScript Interview Question by pavel_lishin on Thursday January 20, 2011 @01:26PM (#2124651)
It could have been the first question of a series. This would probably make a pretty good screen question, at least.
Re:JavaScript Interview Question by edw519 on Thursday January 20, 2011 @01:06PM (#2124570)
It's not the question itself with which I have a problem; it's the whole approach. Let me explain...

1. Every programmer I have ever worked with (except for an inept few) knew something that I didn't. They could show me a piece of their code and say, "When you do <a>, it causes <b>, the compiler does <c>, the operating system does <d>, which results in <e>." To which I think, "Great. Who cares. I would have just done <x> and been done with it."

2. Looking at someone else's code and asking what it does is great: if you have to maintain that code. Otherwise, who cares? If I want to build something, I build it with what I know. What I know may or may not include the best tool in the tool box, but again, who cares? Something built 90% optimally today always defeats something built 100% optimally tomorrow.

3. Describing what some preexisting code does is a good academic exercise, but that's all it is. In my experience, I have observed zero correlation between programmers who would have done well on this question and those who could build and deploy great stuff quickly.

4. For some things, it's absolutely critical to know what goes on under the hood. For others, it's a waste of time. Something than improves performance 1000x or improves up time to five nines is the former. Something that's slick is probably (but not always) the latter. I think this question is probably the latter.

If I have 15 to 30 minutes with someone and want to find out how well they'll be able to build something, I'll have them build something and ask questions about what they just wrote. I have always learned more about them this way than by looking at 3rd party code.

Re:JavaScript Interview Question by bcrescimanno on Thursday January 20, 2011 @01:20PM (#2124622)
I don't completely disagree with you; but I do have some comments (numbered per your items):

2. In a lot of jobs, the ability to read, maintain, update, and extend existing code is considered far more valuable than "building it yourself in your own way." While it's true that there's "more than one way to skin a cat," I'd rather be consistent within a single codebase about how we're skinning that cat. If you can't read and understand code that came before you, you're going to limit your career options to doing nothing but one-off client work.

3. Depends on what you believe "very quickly" means; I would argue that someone who can read and extend preexisting code can work faster than an engineer who wants to build everything him-or-herself.

4. This question isn't a case of performance optimization (though it certainly can be seen that way if you want to talk about the memory and cpu implications of creating tons of functions). This question exposes whether a candidate has an understanding of some pretty fundamental concepts of using closures within javascript and how they impact scoping.

I totally agree that you also want to get a candidate to build something; but this question is very useful at exposing their understanding of how javascript truly works.

Re:JavaScript Interview Question by axod on Thursday January 20, 2011 @01:51PM (#2124773)
2. If you can't read code well, how the hell are you going to be able to write code well? Too many programmers are terrible at reading code and that correlates IMHO with being terrible at writing it.

If you're planning on being an author, it's useful to first be able to read, and to read loads. That's how you learn.

The interview question is a simple rookie js question that basically asks "Do you know javascript to any degree".

Re:JavaScript Interview Question by tocomment on Thursday January 20, 2011 @01:52PM (#2124775)
I think you have a very enlightened approach, Edw519. I actually take it one step further and ask candidates to work on problems or portions of problems the company actually has. E.g., how would you approach fixing this bug.

It also has the side benefit of letting candidates see our codebase, bug tracking, etc.

As far as asking how technologies work under the hood. I really don't care if a web developer knows how pointers work, etc. If they can consistently get challenging problems done, that's all I need to know.

Re:JavaScript Interview Question by boneheadmed on Thursday January 20, 2011 @12:35PM (#2124408)
Although I am playing around with javascript every day (primarily with a game engine), I'm not sure that I would answer the questions correctly without messing around with the code in real-time.
Re:JavaScript Interview Question by huertanix on Thursday January 20, 2011 @02:18PM (#2124886)
This seems far too simple for any developer interview; Is this interview made for a web designer who will be making minor changes to JS code? If not, I'd ask something from Resig's Learning Advanced JavaScript series: http://ejohn.org/apps/learn/#10
Re:JavaScript Interview Question by deweller on Thursday January 20, 2011 @12:41PM (#2124440)
Firefox throws an error with this code because of the missing 3rd parameter to addEventListener. I suggest this change:

https://gist.github.com/788249

Re:JavaScript Interview Question by heyrhett on Thursday January 20, 2011 @12:45PM (#2124462)
The questions are all still valid, but thank you for the update, and I made the change :).
Re:JavaScript Interview Question by ivquatch on Thursday January 20, 2011 @01:37PM (#2124704)
Probably not the best way to do it, but I've done something like this before.

els[i].addEventListener("click",(new function(){var this._i = i; function message(){alert(_i);}}).message);

Re:JavaScript Interview Question by bcrescimanno on Thursday January 20, 2011 @12:38PM (#2124430)
Seems like a great question to me; lots of JS developers use closures without any real understanding of the implications of using a closure.
Re:JavaScript Interview Question by axod on Thursday January 20, 2011 @01:49PM (#2124765)
Boring rookie question. Add a closure. I expect it does a good job of sorting out people who know js from those that have no clue though.
Re:JavaScript Interview Question by smysore on Thursday January 20, 2011 @05:42PM (#2125625)
why hasn't anyone suggested this: els[i].addEventListener('click', new Function("","alert("+i+");"),false);

it works fine and it's much shorter and easier to read than nested function declarations

Re:JavaScript Interview Question by austintaylor on Thursday January 20, 2011 @12:34PM (#2124404)
I think they all alert '3' because of the missing 'var' keyword.
Re:JavaScript Interview Question by mustpax on Thursday January 20, 2011 @12:44PM (#2124454)
Just adding var wouldn't be enough, you're still referencing the variable from the outer scope. You need to create your own copy. Instead of:

    els[i].addEventListener('click', function(){alert(i);});
Do:

    els[i].addEventListener('click',
        function() {
            var j = i;
            alert(j);
        });
Edit: This is wrong, archgoon has the correct answer below. That'll teach me for jumping on closure problems in the morning :)
Re:JavaScript Interview Question by archgoon on Thursday January 20, 2011 @01:05PM (#2124563)
That won't work either. You're still setting the variable to the global variable i. The only way I can think of doing this is as follows

els[i].addEventListener('click',function(k){function(){alert(k)}}(i));

EDIT: See lhorie's suggestion below for a much cleaner way of doing this. http://news.ycombinator.com/item?id=2124532

Re:JavaScript Interview Question by theoretical on Thursday January 20, 2011 @12:57PM (#2124528)
That won't quite work, as you're still just copying the value of i when that function is executed, which will be 4.

You could make the function take a parameter, then return a function which uses that parameter, or use currying.

Edit: I've posted a working version in my comment further down, http://news.ycombinator.com/item?id=2124559

Re:JavaScript Interview Question by mumrah on Thursday January 20, 2011 @01:47PM (#2124753)
I create a closure outside of the event registration: http://pastebin.com/igzWkgKF
Re:JavaScript Interview Question by SMrF on Thursday January 20, 2011 @12:54PM (#2124516)
I think you want var j = i outside the function.

Edit: Oops, this is wrong as well. :-)

Re:JavaScript Interview Question by tremendo on Thursday January 20, 2011 @12:56PM (#2124523)
alert('"'+i+'"')
Re:JavaScript Interview Question by emehrkay on Thursday January 20, 2011 @12:45PM (#2124463)
Thats not the reason why it will alert 3 (it will alert 4, btw).

Here is a fix http://jsfiddle.net/hBe3c/

Re:JavaScript Interview Question by watmough on Thursday January 20, 2011 @12:41PM (#2124442)
This is my thought also, but I'm unsure of how to lock in the correct integer value to the alert, such that clicking each li element pops up the correct number.

I'm guessing one would have to create an object with a scope that holds the right value, on each turn through the loop.

Re:JavaScript Interview Question by bcrescimanno on Thursday January 20, 2011 @12:43PM (#2124451)
You're on the right track; they'll all print 4; but it's not because of the missing var keyword.
Re:JavaScript Interview Question by Timmy_C on Thursday January 20, 2011 @12:45PM (#2124459)
If you run the code you'll find that they all alert('4'). However, the third parameter of els.addEventListener() so you'll get an exception if you run the code verbatim.
Re:JavaScript Interview Question by krmmalik on Thursday January 20, 2011 @12:28PM (#2124371)
Is it poor etiquette to state what i think the answer is?
Re:JavaScript Interview Question by Wilduck on Thursday January 20, 2011 @12:32PM (#2124396)
Please do.
Re:JavaScript Interview Question by lhorie on Thursday January 20, 2011 @12:57PM (#2124532)
this is what I usually tell people to do:

  var els = document.getElementsByTagName('li');//use var unless you really really really meant global
  for(var i=0; i < els.length; i++){
    (function(i) {//creates new scope for each iteration
      els[i].addEventListener('click', function(){alert(i);}, false);
    })(i);
  }
Re:JavaScript Interview Question by aaronblohowiak on Thursday January 20, 2011 @01:05PM (#2124565)
i agree with the choice of code, but I have a different style for laying out the code.

i dislike the declaration and immediate execution of an anonymous function. i much prefer to give it a name, move it out of the loop itself and then call it within the loop. it makes reading the code more top-to-bottom.

with this approach, when I get to the anon func declaration, i have to scan down looking for when it is invoked. while indentation helps, i then have to backtrack up to the beginning of the func declaration.. and hopefully i haven't lost track of what the execution context for the anon func is and so forth...

Re:JavaScript Interview Question by lhorie on Thursday January 20, 2011 @01:43PM (#2124729)
I don't generally care too much to talk about style when the problem at hand is that someone has been banging their head against the desk for the past two hours and they just want it to work (and, in my experience, this usually is the case, for some reason)

But yeah, if we're gonna be super nitpicky, yeah sure, improve the for loop also, while we're at it.

  for (var i = -1; els[++i];) {//given the code in the loop body, this is shorter and faster
Re:JavaScript Interview Question by heed on Thursday January 20, 2011 @02:50PM (#2125010)
Wouldn't var i have to be set to -1:

  for (var i = -1; els[++i];)  ?
Otherwise, the alert won't trigger on the first li element.
Re:JavaScript Interview Question by lhorie on Thursday January 20, 2011 @02:56PM (#2125047)
Hah, good catch. Was thinking of i++ for some reason. Fixed.
Re:JavaScript Interview Question by kenjackson on Thursday January 20, 2011 @01:37PM (#2124705)
Does this work (from a non-JS person -- I like reading JS books, but don't code in it at all). This is certainly less elegant, but seems easier to follow:

  var els = document.getElementsByTagName('li');

  for(i=0; i < els.length; i++){
    var j = i;
    els[j].addEventListener('click', function(){alert(j);}, false);
  }
Re:JavaScript Interview Question by lhorie on Thursday January 20, 2011 @01:56PM (#2124791)
No, it doesn't because j is in the same scope as i.

Your confusion is because of a javascript quirk

  for (...) {
    var foo = bar
  }
is actually the same as

  var foo
  for (...) {
    foo = bar
  }
Notice how you only ever have one foo

What you need is:

  for (...) {
    (function(bar) {
       var foo = bar
    })(bar)
  }
which create a new foo every time you loop
Re:JavaScript Interview Question by buerkle on Thursday January 20, 2011 @01:45PM (#2124744)
That doesn't work. Variables in javascript are not block scoped but function scoped.
Re:JavaScript Interview Question by kenjackson on Thursday January 20, 2011 @01:52PM (#2124774)
Thanks. Good to know.
Re:JavaScript Interview Question by theoretical on Thursday January 20, 2011 @12:44PM (#2124456)
It won't alert quite what you want - when you click on each element in the list, it will alert "4".

This is because the function assigned to the click event of each li is bound to the "i" variable used in the loop by a closure. Variable i is incremented to 4 before the loop ends, so that is what each will print.

You could use make the function used in the click handler take a parameter, then use partial function application (or currying) to fix the value of the parameter.

Re:JavaScript Interview Question by Timmy_C on Thursday January 20, 2011 @12:51PM (#2124501)
The function in the click handler does take a parameter 'e' (...or whatever you call it) which is an Event object. But I think you're on to something by using currying.
Re:JavaScript Interview Question by theoretical on Thursday January 20, 2011 @01:03PM (#2124559)
Well yes, the function is called with a MouseEvent as one of the arguments, so you could use the "arguments" object to access it.

What I was thinking of, was something along the lines of:

  // From http://ejohn.org/blog/partial-functions-in-javascript/
  Function.prototype.curry = function() {
    var fn = this, args = Array.prototype.slice.call(arguments);
    return function() {
      return fn.apply(this, args.concat(
        Array.prototype.slice.call(arguments)));
    };
  };

  els = document.getElementsByTagName('li');
  for(i=0; i < els.length; i++){
    els[i].addEventListener('click', function(x){
        alert(x);
    }.curry(i), false);
  }
Re:JavaScript Interview Question by robterrell on Thursday January 20, 2011 @12:49PM (#2124491)
Wrap the line of code inside the loop inside another function, which will have the effect of binding the iterator i to the desired value before the event handler anonymous function is created.
Re:JavaScript Interview Question by meeech on Thursday January 20, 2011 @12:48PM (#2124480)
is it cheating to just use a custom property?

https://gist.github.com/788257

Re:JavaScript Interview Question by loganlinn on Thursday January 20, 2011 @01:02PM (#2124553)
Seems to be avoiding the intended topic: scope and its temporality