Javascript scopes. Always a source of confusion, explanations and counter explanations. See this SO question, this interesting explanation or this article (among others).

Even if I write this for my own and selfish future reference, here it is what one should have in mind when coding/debugging Javascript code, related to scoping.

Only Global and Function Scopes

Further from the global scope, a new scope is only created in Javascript when a function is defined. This means that in most cases a new bloc (surrounded by a pair of brasses) doesn’t create a new scope as it happens in C or Java. A quick example:

This writes “2” to the console. In a c-like language the variable A would be “redeclared” and the assignment won’t take any effect out of the if block.

However, if the variable was declared in a function, it would override the outer (global) scope, as follows

In the function the value of àis "2", but when code flow is returned fromf,a` referes back to the global scope, having the value “1”.

Simple, isn’t it?

A more problematic example

Suppose you want to dynamically create three buttons and add them to a page, say button 0, button 1 and button 2. When any of the buttons is clicked, an alert is shown with the button’s number. Without any framework (I like Javascript frameworks, I really do!) you might start with something like this:

For a javascript starter (and not so starter) it may seem all nice and clean. You even use an anonymous function, how functional you are! However, if you run the example and click any of the buttons, the alert that is shown would tell you always that button 3 was clicked. Button 3?! Yes, button 3.

The event listener is an anonymous function and, as we know, a javascript function creates a new scope. But, looking closer, the variable ìcomes from the outer scope. And what is the outer scope? The loop? No, the function! After the loop ends ìwill be equal to 3, and that is what what the event listener will use lately when it is called. One can think about this as if ì` is declared at the top of the function’s code (this concept is usually called hoisting).

To solve it one must provide a fresh ìvalue to the event listener. If processing an array one can easily use [array.prototype.foreach](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach), any of theforeach/èach` implementations present on many popular frameworks or rule our own (which is nice). In this case, as we are running a simple for loop (and want to learn stuff without beautiful frameworks), the easiest approach is employing immediate functions.

Immediate Functions

Immediate functions are simply defining a anonymous functions and calling them right away, as follows:

This works because a function definition is a expression that returns a function value that is called using the ()function call operator.

So for our buttons example, immediate functions can be employed to create a closure that associates the ì`index value with the button’s click event listener. The following code now works as expected:

Note the creation of the the event listener: a new anonymous function is returned with the proper index in scope (using a closure, so f***ing functional!).

Conclusion

Javascript has some peculiarities and not so obvious design choices, at least for those coming from C, C++, or Java. However, with its good functional programming support and many frameworks it is a tolerable language to code in, if aware of these and other gotchas.

The guys at Codacy have a great post about this stuff which I recommend reading. The book Secrets of the JavaScript Ninja from jQuery’s creator John Resig explains all of this and much much more, and very fun to read too.

Share on: TwitterFacebookGoogle+Email


Comments

comments powered by Disqus