Scope vs. Context in JavaScript

Scope and context may seem similar, but they actually have very different functions

David Engel
Jun 3, 2019 · 6 min read
Photo by Jp Valery on Unsplash

At first glance, computer code looks like an esoteric combination of keystrokes that go on for hundreds or even thousands of lines without much organization or cohesion. In reality, code is a highly organized and hierarchical system where processes are synchronized but separated.

Simple principles govern how code is structured and interpreted by computers. These principles build off of each other, repeatedly compounding to create more complex and efficient applications. This post will describe two of these principles in particular: scope and context. Although these two principles are undoubtedly important in other coding languages, I will focus on their most basic behaviors in JavaScript specifically.

Scope and context can seem very similar, and if you get them confused from time to time, don’t feel alone. Like many aspects of coding, scope and context can be difficult to visualize and can hinder JavaScript newcomers from advancing their capabilities as quickly as they’re capable of.

One possible reason for this confusion is because scope and context both refer to when variables or certain keywords become relevant, and what exactly they refer to when they’re called upon. Let’s take a closer look at scope first.


Scope

Example of a globally scoped variable

Local scope refers to variables that are accessible within the boundaries of their function. In this example, we have our initial declaration of the variable dog at the top of our file, which is assigned to the string of “goodBoy.” Immediately below, we console.log the dog variable.

As expected, this first console.log prints ‘goodBoy,’ as seen on the right side of the image. Then, we have a function of showScopeExample(), which reassigns our dog variable to the string of “badDog.”

This function is immediately invoked, but when we console.log “dog” for the second time on line 10, it still prints as “goodBoy.” Even though the second console.log occurs after we reassign the variable inside of the function, the dog variable is not currently capable of returning as “badDog.” This is by design.

Our re-declaration of dog inside of showScopeExample() is locally scoped. The easiest way to know this is to look at its location. The re-declaration lies in between opening and closing curly brackets, which act as barriers to the relevancy of these variables.

Limiting the accessibility of the variables declared inside of functions allows us to reuse variable names that may apply to separate parts of our code. Locally scoped variables also prevent our code from having tens or hundreds of global variables floating around the global space unnecessarily. It’s also good practice to exercise proper abstraction in our JavaScript by limiting access to variables to areas where they are needed. Let's look at a slightly varied example…

In this example, all we’ve changed is the location of the second console.log, which is now inside the boundaries of the showScopeExample() function. As seen in the console to the right, the first console.log still prints “goodBoy” as expected.

Unfortunately, our second console.log now prints “badDog” when we invoke showScopeExample() (poor pup). This is because our second console.log is now held within the boundaries of the curly brackets, and it will print information that is located within the same scope.

Finally, the third console.log returns to printing “goodBoy.” This is again because it does not have access to the local reassignment and resorts to the initial declaration.


Context

Invoking this in the global space will return the entire window object. This is because the window object is the starting point of all the code we write. Give it a try, and you’ll likely get something like this in response…

“This” refers to the window object — the outermost context of our code

The endless white text we get in return is the window object. The first rule of this is that by default, it refers to the window object. If you ever get the chance, you should explore the window object returned from invoking this in the global context.

But what happens if we invoke this somewhere other than the global context? If we invoke this in the context of a new object, it will return that object, just as it returned the entire window object. Let’s look at a simple example and then build on it.

Now “this” refers to the newContextObj — a more limited context than previously

In the example above, we’ve created a new object which we’ve named newContextObj. When we invoke the method invokeThisInNewContext() it returns the entire newContextObj.

This is the same as when it returned the window object in our first example. The only difference is that the window object is a very large and complex object, and our newContextObj is very small and simple. The second rule of this is that when it is invoked in the context of an object, this will refer to that object.

Finally, the third rule of this is a bit more complicated. In JavaScript, we use classes to create multiple instances of objects that share properties, even though those properties may differ in value.

For example, we could have a class that produces instances of a car object. Despite the fact that the cars all have sizes, capacity, and engine types, these three things probably differ from car to car. Below is an example of this being invoked in the context of an instance of ContextObj.

What we see in the example above is the invocation of the whereIsThis() method on our instance of ContextObj. In this third and final example, the keyword this refers to this specific instance of ContextObj, no matter how many instances of ContextObj exist in our code.


Conclusion

Open your preferred text editor and start creating functions and object of your own. Mess around with variable placement in your functions. When do you have access to them and when do they return undefined?

Create increasingly complex objects and invoke this in increasingly specific and limited contexts. There is no better way to become comfortable coding than by getting your fingers on the keyboard and struggling through concepts, one at a time.

Better Programming

Advice for programmers.

David Engel

Written by

I’m a front end developer in Denver, CO.

Better Programming

Advice for programmers.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade