

JavaScript Interview Question - heyrhett
http://cam.ly/blog/2011/01/javascript-interview-question/

======
raganwald
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/...](https://github.com/raganwald/homoiconic/blob/master/2010/10/let.md#readme)

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 :-)

------
dmvaldman
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.

~~~
bcrescimanno
"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.

~~~
dmvaldman
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.

------
Xavi
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.

~~~
pdelgallego
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.

~~~
Xavi
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`.

~~~
erikwiffin
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?

~~~
Xavi
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>

~~~
jaysoo
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 !!"

------
smysore
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

~~~
bcrescimanno
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.

------
edw519
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.

~~~
bcrescimanno
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.

------
boneheadmed
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.

------
huertanix
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>

------
deweller
Firefox throws an error with this code because of the missing 3rd parameter to
addEventListener. I suggest this change:

<https://gist.github.com/788249>

~~~
heyrhett
The questions are all still valid, but thank you for the update, and I made
the change :).

------
ivquatch
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);

------
bcrescimanno
Seems like a great question to me; lots of JS developers use closures without
any real understanding of the implications of using a closure.

------
axod
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.

------
smysore
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

------
austintaylor
I think they all alert '3' because of the missing 'var' keyword.

~~~
mustpax
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 :)

~~~
archgoon
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>

------
krmmalik
Is it poor etiquette to state what i think the answer is?

~~~
Wilduck
Please do.

~~~
lhorie
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);
      }

~~~
kenjackson
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);
      }

~~~
buerkle
That doesn't work. Variables in javascript are not block scoped but function
scoped.

~~~
kenjackson
Thanks. Good to know.

------
meeech
is it cheating to just use a custom property?

<https://gist.github.com/788257>

~~~
loganlinn
Seems to be avoiding the intended topic: scope and its temporality

