in Code

Since the start of 2015, I’ve been working on some JavaScript courses on Treehouse and elsewhere. In an effort to improve, I’m going to do a JavaScript code challenge every Monday for at least 10 weeks. Here’s the first one. I would love feedback in the comments!

Here is a link to the original problem on Interview Cake. In short, you have the following code. The syntax is correct, but the behavior is off.

<button id="btn-0">Button 1!</button>
<button id="btn-1">Button 2!</button>
<button id="btn-2">Button 3!</button>

<script type="text/javascript">
    var prizes = ['A Unicorn!', 'A Hug!', 'Fresh Laundry!'];
    for (var btnNum = 0; btnNum < prizes.length; btnNum++) {
        // for each of our buttons, when the user clicks it...
        document.getElementById('btn-' + btnNum).onclick = function() {
            // tell her what she's won!
            alert(prizes[btnNum]);
        };
    }
</script>

It didn’t take me long to figure out the actual issue, but the solution was a different story. It eluded me for several minutes. Here’s my solution minimized.

<button id="btn-0">Button 1!</button>
<button id="btn-1">Button 2!</button>
<button id="btn-2">Button 3!</button>

<script type="text/javascript">
    var prizes = ['A Unicorn!', 'A Hug!', 'Fresh Laundry!'];
    var press = function (x) {
        document.getElementById('btn-' + x).onclick = function() {
            console.log(prizes[x]);
        }
    };
    for (var btnNum = 0; btnNum < prizes.length; btnNum++) {
        press(btnNum);
    };
</script>

(If you’re looking for a very detailed and amazing breakdown of the issue, I would recommend heading over to Interview Cake.)

The overall issue is when you press a button, you’ll get undefined each and every time. If you throw a console.log(btnNum) in the .onclick function, you’ll notice you return “3”. There isn’t a prize with the index of 3 (the length is 3, but the highest index is 2). The .onclick function does have access to the btnNum variable (functions have access to variables outside their scope). However, it only has access to a frozen value. Therefore, by the time you press the button, the for loop has already run and bumped btnNum to 3.

To fix this, I moved the click function outside of the for loop. First, I created a function that would accept a single value. The function grabs the value, gets the associated button, and sets an anonymous function to be executed when that button is pressed. When pressed, the user is alerted of the prize at the same index value. Finally, I kept the same for loop. This time, I passed the btnNum variable to the press function ensuring that the function gets executed each time (rather than only on 3).

Leave a Thought