Everything you need to know about the JavaScript Scope

Akarshan Bansal
The Startup
Published in
6 min readJul 19, 2019
Why is JS scope so weird

I remember my early days as a JS programmer, failing to understand why people were using bind/call/apply methods and how to use or manage the this keyword. If you’re new to JavaScript and have just started writing some event handling functions in jQuery or created some basic components in Angular or React, this information will definitely help you out in the long run.

Lexical Scoping

You will find the term “lexical scoping” on most websites when you’re studying JavaScript but what does it mean in a nutshell.

Lexical Scoping is a design paradigm where a variable can only be used within the block in which it is defined. This means that every block has its own scope.

In JavaScript, we have lexical scoping combined with function scope. So, instead of creating a different scope in every block, JavaScript creates a new scope for every function.

Let’s look at an example. If you run the following code in your browser console, you will get the value “1” as output. But how was this program read by the browser?

Lexical Scope

firstFunc and secondFunc are functions which is why JS creates a new scope for both of them. So whenever a variable is referenced, JS looks for the variable in the current function block and then moves outwards until it reaches the global scope.

In line 6, we are declaring a new variable with the same name as the global scope but since we’re using the var keyword, we are not overriding the variable in the global context.

In line 3, since a is not present in the immediate function scope, JS moved outwards and retrieved the value from the global scope. So when we reach line 9, since the two functions have independent scopes, the value printed is “1” which the firstFunc receives from the global scope.

Let's see how the ‘this’ keyword works with respect to scope.

Using this object

In JavaScript, the behavior of this keyword is a little peculiar if you’re not familiar with it. By default, ‘this’ refers to the object that contains the function. So if a function is created as a property of an object, ‘this’ will refer to that object. But if you create a new function anywhere else in your code, ‘this’ will refer to the global window object.

Let’s take a look at the following program.

This is the output.

Let me explain what is happening. In line 5, the getDetails function is created as a property of the person object which sets the scope of getDetails method to the person object. So, ‘this’ will refer to the person object here. When we create the innerFunction method, a new scope is created and this will now refer to the global window object.

So if we add some data in the global scope with the same property names, we should be able to see them printed inside the inner function. Let us add the following line at the top of the previous program.

Now let’s see the output

Since ‘this’ is now referring to the global scope, the values from the global scope are being printed.

I hope this explains to you how scope and this work together in JavaScript. This behavior is queer, to say the least, and that’s why it's considered a poor design. This issue has been fixed in ES6 with arrow functions. So if you’re not aware of them, go check them out.

Bind / Call / Apply

Javascript has a powerful yet confusing feature where it allows you to explicitly set the execution context of a method and reuse that method for different objects. This can be used to fix the problem that we discussed above with the ‘this’ keyword.

Let’s see the following program.

Here we have a method getDetails inside person1 object which is printing some properties that are bound using the ‘this ’keyword. I want to use the same method to print the details of person2.

Bind / Call / Apply => All these methods are used for this exact problem.

To use Bind, add the object, that you want the execution context set to, inside the method argument. See the example on line 16.

Apply and Call have some additional uses. Let’s see the following program

We have added 2 arguments inside getDetails method. To call this method with the necessary arguments while simultaneously changing the execution context, we can use the call and apply methods.

In call, the data is added as arguments following the object argument (1st arg). See line 16 in the previous program.

In apply, the data is added as an array following the object argument (1st arg). See line 17 in the previous program.

Closures

A JavaScript lesson in scope cannot be completed without talking about closures. We won't discuss them at a very advanced level but just enough to understand how they affect scope.

Simply put, a closure is a combination of a function and the scope around it. In JavaScript, every time you create a new function, closures are created which give you access to the outer scopes including global scope.

Let’s try to visualize this in the browser. See this program.

To visualize a function as an object and to see all its properties, we can use console.dir. This is the output that you will see.

You can see very clearly from the logs that the outerFn has access to global variable name1 and the innerFn has access to outerFn variable name2. Lets expand the innerFn and outerFn objects and see how closures work to give this access.

outerfn

You can see that a closure has been created for the global scope inside outerFn.

innerFn

Here, 2 closures have been created for global scope and outerFn scope. So whenever we use values from outside the current function definition, a closure is added to the scope chain.

I hope this lesson provides clear insight as to how scope works in JavaScript, the use of ‘this’ keyword and using call/bind/apply methods. Hopefully, you learned something today. Until next time. Cheers!!

--

--

Akarshan Bansal
The Startup

Front end developer with Accenture Products. Passionate about JS, music and traveling.