Understanding javascript scopes and lessons learned

One of the things when working with Javascript that gives me some headaches is how it deals with scopes. There is no magic behind that, however I found the syntax to be a bit confusing when reading the code (ex: var, let, const, global declaration), as sometimes it requires to go in ‘detail’ mode.

When talking about scopes, I like to think about it as the context of the of the line of code/variable it is running.

Scope inspection on Chrome

Scope inspection on Chrome

The scopes we normally refer to can be at different levels:

  • Global: Variables in memory at this scope will exist until the web browser window is closed or detached
  • Function: They are also called local scopes, and represents
  • Block: They are contained within a piece of code. Could be a if, switch, loop… or just simple curly brackets

On top of that, we can have nested scopes and variables shadowing other variables on different contexts. Until here, everything is normal and very similar to other languages (compiled or interpreted). However, in Javascript (based on my experience), I feel a wrong declaration of a variable could lead to some headaches and what it is worst, memory gc issues, thread blocking on the client…

Refreshing scope concept through examples

As a first example, we will be working with the following code:

In this code the following context are created/updated:

  • Global context (created by default)
  • Context for function f1
  • Context for function f11, which is isolated from f12 context but nested from f1 context
  • Context for function f12, which is isolated from f11 but nested as well to f1 context

A representation of the previous code could be the following diagram: (each node on the diagram is a scope)

Everything seems clear, no doubts about what it does and the variables we can use.

Once we know what is happening, let’s see this second example:

As we can see, when accessing proverb variable from outside of the function scope, javascripts throws an error, the variable is not accessible (undefined).

However, the following will work:

The only thing that changed was the variable declaration. I normally prefer to have always a declaration of the variable, setting things by default infers the developer to know what they are doing and I think it is good to be strict in this type of things.

Normally, software developers do not have to deal with code as easy as this one, and debugging an issue within thousand of lines of code could be much more complicated than this example (You don’t want to spend the evening debugging an issue that could have been solved just specifying explicitly the scope where a variable resides).

Declarations: var, let and global

As we said before, a variable can be scoped to a block code, a function or to global/window. For block code scope we use let and for function,global scope we will use var. Depending if we declare the variable within a function or outside, the scope will be different.

Here you can see some examples:

Using var or let for variable declaration can affect the memory garbage collector. Forcing the garbage collector to look for more references means the main thread on the client is busy, hence problems may appear related to responsiveness or ui rendering. Normally GC work with the ‘Mark & Sweep’ strategy, so the more variables are in memory (even when not used anymore, the more time it will make to the algorithm to release the free objects)

This is in my opinion the main difference a javascript developer has to have in mind when declaring variables and could affect the program GC behavior massively.

Exploring scopes at runtime

Sometimes the scope of javascript running is not clear. I normally use Chrome Debugger Tool: you can put breakpoints on lines you want to see the state of the program and it makes really easy to find out what is the issue.

As an example lets have a look to the saySomething example mentioned before:

Running the script on node-debug, we can inspect easily the code. Having a breakpoint on the proverb evaluation should give us a state of the context:

Node-debug breakpoint on existing function scoped variable

Node-debug breakpoint on existing function scoped variable

We can see the variable is declared on the scope. If we continue debugging and execute until the next proverb evaluation:

Node-debug breakpoint on non existing global variable

Node-debug breakpoint on non existing global variable

Learnings

  • Communicate your team to follow always the same rules for declaration. Be as much explicit as possible.
  • It is a good practice was to use always declarations and not leave anything to be assigned by default by the javascript runtime.
  • Avoid use of global if possible, as these variables will be always on memory. You don’t want to end up with a contaminated global scope. This will also help to the GC to perform better and not block the thread for a big time (more than 15 ms is normally not acceptable)

Links

A saw a couple of links that are really good in case you have some extra minutes:

  • http://stackoverflow.com/questions/500431/what-is-the-scope-of-variables-in-javascript
  • http://robertnyman.com/2008/10/09/explaining-javascript-scope-and-closures/

Disclaimer: I am not a javascript architecture professional, my main focus is Java but like to work on my free time on javascript. Any constructive feedback, suggestion is highly desired.

 

4 thoughts on “Understanding javascript scopes and lessons learned

  • Can I just say what a relief to find someone who actually knows what theyre talking about on the internet. You definitely know how to bring an issue to light and make it important. More people need to read this and understand this side of the story. I cant believe youre not more popular because you definitely have the gift.

    • Ey Susanah, those are really kind words. Thank you! I started the blog more as a way to get some feedback from people and learn during the process. There is a saying that says: “You never learn it until you explain it”, so decided to put my thoughts and go with the flow. If I am completely wrong on some concept I will just correct it and learn from it 😉
      The blog is relevantly new but glad to see your comment. Really keeps me pushing forward 🙂

Leave a Reply

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