JS Demystified 03— Scope
A humble attempt to demystify tricky concepts in JavaScript

JS Demystified Series

Intro
Now that we understand hoisting, it’s time to talk about scope.
Don’t worry if you aren’t comfortable with hoisting. Here are my posts discussing it in detail. Take a moment to refresh your memory there and jump right back in.
JS Demystified 01 — Variable Hoisting
JS Demystified 02 — Function Hoisting
Test Your Knowledge
As usual, we start by testing your knowledge with a quiz. Can you tell what will following four console.log
print out?
The answer is:
1: Hello!
2: undefined
3: Ciao!
4: Hello!
— and yes, in that order!
It might look confusing, and I don’t blame you. We really need to have a solid understanding of hoisting and scope to get this one right. Being comfortable with these two concepts is essential as a JavaScript developer, as it will help you write safe code and debug faster.
So without further ado, let’s dive into it.
N.B. Scope and execution context are closely related, but not the same. It is a separate topic on its own, so I’ll keep that for another time. We will focus on understanding scope in this post.
What is Scope?
Scope in JavaScript defines which variables and functions you have access to, depending on where you are (a physical position) within your code.
Consider the following two examples.
Why does the second console.log
in the example 2 throw an error?
The difference between the two is that the variable greet
is defined in different places; outside the sayHi
function in the first example, and inside in the second. That dictates whether you have access to greet
from outside the function, i.e. where console.log('2: ', greet)
sits. This is because greet
is globally scoped in the first example, whereas it is locally scoped in the second.
So what are global scope and local scope?
Global Scope
The global scope is the outermost scope and is pre-defined even before you write a single line of code. Typically, you only have one global scope and it’s automatically created by the JavaScript engine. You can easily check what’s inside the global scope in your browser.
Open up the developer tool (shortcut for Chrome is alt + cmd + i
), go to the console panel and type this
. The this
keyword by default points to the Window
object that sits within the global scope.

Now, in the same console panel, declare and initialise a variable greet
. Then, access the Window
object again by typing this
. If you expand the Window
object and scroll all the way down… there it is! The greet
variable has been added as a property of the Window
object and is globally available. So if you type greet
in the console, it will give you "Hello!"
.

Global variables can be accessed and modified from any other scope.
Local Scope
Local scope is any scope created within the global scope. Every time a new function is declared, a new local scope gets created, and variables declared inside the function belong to that unique scope.
During the execution phase, local variables can only be accessed and modified within the same scope. As soon as the JavaScript engine finishes executing a function, it exits the local scope and moves back to the global scope, losing access to the variables within that local scope.
This is why the second console.log
in example 2 threw an error complaining that greet
is not defined, when we tried to access a local variable from the global scope.
Here is another example to demonstrate what we just discussed.
You can have multiple local scopes within the global scope. Each local scope is an isolated entity, so variables that belong to a scope is confined to that specific scope.
Hoisting and Scope
Alright, we’ve covered global and local scope so far. Let’s go back to our quiz and see if we can understand what’s going on. Try to follow the snippet as if you are the JavaScript engine executing the code — start from the first console.log
at line 9, then move on to the second one inside the sayHi
function, and so on.
Can you explain why each of the console.log
will result in the respective value below?
1: Hello!
2: undefined
3: Ciao!
4: Hello!
More specifically, can you explain why console.log('2: ', greet)
at line 6 results in undefined
?
Below, I annotated the snippet to highlight possible sources of confusion.
The key is hoisting — variables and functions are hoisted within the scope they belong to.
Let’s walkthrough the quiz code step-by-step, from the JavaScript engine’s point of view, combining the knowledge of hosting and scope.
During the memory creation phase:
- line 1:
var greet
gets hoisted to the global scope - line 3:
function sayHi () {...}
gets hoisted to the global scope - line 5:
var greet
withinsayHi
gets hoisted to the local scope
During the execution phase:
- line 1: Global
greet
gets assigned toHello!
- line 9: The value of global
greet
isHello!
- line 10:
sayHi
gets called, the JavaScript engine enters the function - line 4: The JavaScript engine reaches
console.log
, looks for a variablegreet
, and finds it within the current local scope. However, the localgreet
hasn’t been assign to anything yet, hence the value isundefined
. - line 5: Local
greet
gets assigned toCiao!
- line 6: The value of local
greet
isCiao!
. The JavaScript engine exits thesayHi
function and comes back up to the global scope. - line 11: The engine has access only to the global
greet
, which isHello!
Phew… got it?
Not so bad after all, if we apply everything we’ve discussed :)
Wrap-up
Do you feel more comfortable with hoisting and scope? Don’t worry if it’s still confusing. It takes time for these concepts to sink in, but keep thinking about it whenever you code. Keep having a go at it, again and again. And it will be your second nature.
This time, I have a gift for you to take home.
Can you explain why the second console.log
prints out Hello!
? You need to find one caveat that we haven’t covered explicitly to explain this. Can you find it out? Post your answers when you do :)
Please post any feedback, questions, or requests for topics. I would also appreciate 👏 if you like the post, so others can find this too.
Thanks, and see you next time!