Variable Scope and Closure in JavaScript

Brandon Galloway
5 min readJan 16, 2021

A dive into one of the harder concepts to grasp in JavaScript

Closures are described by many as the magic that makes JavaScript so powerful. A closure is a function that remembers its outer variables and has access to them. In JavaScript, all functions are naturally closures with exception to The “new Function” syntax. Understanding scope is key to understanding closure. In this article I will discuss what you need to know about scope to grasp closures in JavaScript.

Before going further it would be good to point out that I will be using examples of variables declared with let and const to keep things simple. From my experience the var variable declaration is much less used because it can cause issues with its unique scoping properties. I would advise that you stick to declaring variables with let or const to make your code more readable and easier to understand.

Scope is used to manage a variable’s accessibility. Inside the scope, you can access the defined variable but outside the variable is not available. Below is a simple example where the greeting constant is defined in the scope of the function and cannot be accessed outside of it.

Block Scope

Block scope is the environment that exists in between the curly braces {…}, also known as a code block. If a variable is defined inside of one of these code blocks, then it is only “visible” within that block. Examples of JavaScript code that exists within code blocks are if-else statements, function declarations, and any type of loops. Scoping gives each block of code its own private environment or its own local scope. How awesome is that! Scopes can also be nested, meaning we can have one code block within another. Below is an example of a function declared as run that has an if statement nested within it. Each of these code blocks has their own scope. As you can see, the if-statement has access to the message constant but there is a reference error when trying to retrieve the friend variable. What’s that all about?

A function with a reference error because it makes a call for a variable that it doesn’t have access to.

The scope contained within another scope is called an inner scope. The scope the wraps the inner scope is called the outer scope. In the example, the if block within the run function is inner scope and the run function would be the outer scope.

The inner scope has access to variables in the outer scope but the outer scope does not have access to variables in the inner scope. Think of it as a one-way mirror, where the inner block can look out but the outer block cannot look in.

Global Scope

The global scope is the outermost scope, which is accessible to any local scope no matter how nested it may be. A variable defined within the global scope is called a global variable. Global variables are accessible to any code block.

Below is an example of declaring a global variable and utilizing it within a function. In the global scope, a variable named countdown is defined using let. The variable was defined using let because it needs to be reassigned later on (here is a good resource for const vs. let vs. var). Also in the global scope, the function decCount is defined. The function takes no arguments and reassigns the global variable countdown to the current countdown value subtracted by one. Decreasing the value by one could have also been performed using the decrement operator. After decrementing the countdown variable we log it to the console to display its value. After each call we get the countdown variable subtracted by one.

As mentioned before, the inner scope will always have access to the outer scope. Any scope, no matter how nested it may be, will always have access to the global scope. It’s important to remember that the inverse is not true. The outer scope will not have access to the inner scope.

It is best practice to avoid using global variables because of the potential for “collisions” between variables with the same name. All JavaScript files included on a page run in the same scope, so if two functions are defined in the global scope with the same name, one will get overwritten. There are many alternatives to avoid using global variables and functions but that’s outside the scope of this article.

Lexical Scope

Lexical scope is sometimes also referred to as static scope. As mentioned earlier the inner code block has access to the outer code block’s contents. Understanding this helps us understand lexical scope. Lexical scope means that in a nested group of functions, the inner functions have access to the variables and resources in their parent scope. This means that the child functions (inner functions) are lexically bound to their parents.

The code below is a good example of lexical scoping. In the example, the inside function is nested within the outside function. After the outside function is declared, you can see that the inside function still has access the constant hiThere, which lives in its parent function’s scope.

The inside function is an example of a closure because it is able to capture the variable hiThere from its lexical scope. I will dive deeper into closures and how they can be leveraged in a future article.

Thanks for reading and I hope you can use this as a resource during your coding journey. If you enjoyed this or learned anything from it, leave claps and a comment. If there’s something you think I should add, please leave a comment. Stay safe and happy coding!

--

--

Brandon Galloway

Web developer with a passion for science at technology.