Web Fundamentals: Scope and JavaScript Closure – a Primer
One of the biggest buzzwords in the JavaScript language is closure. It’s the subject of many job interview questions at FAANG companies. In this article, we’ll talk about closure and scope, illustrate its concepts with simple examples, and then finish out with a sample question from an interview with one of the bigger tech giants.
Scope
When someone tells you something is or isn’t in scope of a project, what does that mean?
I’d like to think of a periscope or a telescope when I think of the answer to this. These instruments show us all sorts of things within the confines of the lens it has: it’s inscope. If it’s outside thescope, you can’t see past the diameter of the lens. And shining a light on something outside the diameter is not possible. You should be thinking about this as we talk about three very important and distinct types of scope in #" " + var2; }; // console.log(var2); // undefined return second();};init();
Here we have a set of nested functions. Theinit()
function declares a variable called var1, declares a function called second and invokessecond()
.
When the compiler passes through this code the first time, it takes a high level look at what we have:
init()
function- invoke
init()
At this point, we can’t see anything else inside the init() function – we just know the function exists. When our init() func is invoked, the compiler takes another high level look at what’s inside the function:
var1
second()
function- invoke
second()
Theinit()
function knows nothing about what is going on inside thesecond()
block. It can only see what is in itslexical environment – its surrounding state.
Each nested function is in a smaller container, like a set of those Russian matryoshka nesting dolls (see top of page for example if you’re unsure of what they are). The dolls only know about what’s going on inside their container and what’s already occurred or declared/read in the parent. The largest doll for example only knows that the next doll in its container exists. It doesn’t know about any of the other dolls in the set, just what’s in its lexical environment (its state) and what’s already happened (the outer scope).
In essence, we know two things:
- The outer scope can’t see the inner scope.
- The inner scope has access to the outer scope.
Because the outer cope can’t see what’s going on in the inner scope, we can safely say that this is a one-way relationship. Inner can see and use variables from the outer scope, but outer can’t see inner. This is calledlexical scope.
The beauty of lexical scoping is that the value of a variable is determined by its placement in the code. The functions look for the meaning of a variable inside it’s local environment first – if it can’t find it, it moves to the function that defined that function. If it can’t find it there, it moves up the chain to the next defined function.
This becomes a very important concept in JavaScript that will come up time and again as you learn more about JavaScript frameworks and how they work. You can pass down from the outer, but you can never pass “up” in the other direction. This is very important as we get to the major topic at hand:closure.
Closure
Closure’s definition is very similar to that of lexical scope. The main difference between the two is that closure is a higher order function and lexical scoping is not. A higher order function has one basic characteristic: it either returns a function or uses a function as a parameter.
Closure is a function that can access its lexical scope, even when that function is being invoked later.
Both closure and lexical scope have their own variables, can access a parent function’s variables and parameters, and can use global variables. Let’s walk through the following code:
function greeting() { //outer scope (parent function) const userName = "CrrKrma1952"; // parent variable function welcomeGreeting() { // inner function console.log("Hello, " + userName); // accesses parent var return "Hello, " + userName; // terminal statement } return welcomeGreeting; // returns a function (which makes it HOF)} // end of greeting() const greetUser = greeting(); //greetUser(); // Hello, CrrKrma1952
greeting()
function exists, but we don’t know the contents yet.greetUser
exists, but don’t know contents yetgreetUser()
– this invokes the previous line, which, in turn, invokes the greeting() function.- userName declared
welcomeGreeting()
exists, but don’t know contents yet- Return statement below the
welcomeGreeting()
block returns that very same function console.log(‘Hello, ‘ + userName)
; Our console.log here can access the parent scope to get the value of userName- Terminal statement that ends the function and destroys the meaning of the variables inside the code block.
In this code, we are passing around information by nesting functions together so that the parent scope can be accessed later.
Conclusion
In this article, we talked about a pretty hefty JavaScript subject: Scope and Closures. I would recommend branching out and reading several different articles on the subject. The way this is taught can come from a variety of points-of-view – which means, of course, that there’s lots of ways to learn it. I hope this primer was helpful to you! Good luck in continuing your study on closures!

"Career Karma entered my life when I needed it most and quickly helped me match with a bootcamp. Two months after graduating, I found my dream job that aligned with my values and goals in life!"
Venus, Software Engineer at Rockbot
About us:Career Karma is a platform designed to help job seekers find, research, and connect with job training programs to advance their careers.Learn about the CK publication.
