Good morning! Here's our prompt for today.
Understanding Variable Scoping in JavaScript
Let's dig into a fascinating JavaScript example to unravel the mystery of variable scoping.
The Code Snippet
Here's the code we'll be examining:
1var numOfBeers = 5;
2
3function getMoreBeers() {
4 console.log('I have this many beers: ' + numOfBeers);
5 var numOfBeers = 25;
6 return numOfBeers;
7}
8
9console.log('I now have this many beers: ' + getMoreBeers());
What Do You Expect?
Before running the code, what do you think will be printed to the console? Take a moment to think it over.
Execution Results
Go ahead and execute the code. What do you see?
Your job in the interview is to explain why it runs the way it does.
Try to solve this here or in Interactive Mode.
How do I practice this challenge?
xxxxxxxxxx
# This is not applicable to Python
We'll now take you through what you need to know.
How do I use this guide?
Analyzing Output in JavaScript: The Case of Mysterious Beers
The Code and Its Output
Let's look at the JavaScript code snippet and its output when executed:
1var numOfBeers = 5;
2
3function getMoreBeers() {
4 console.log('I have this many beers: ' + numOfBeers);
5
6 var numOfBeers = 25;
7 return numOfBeers;
8}
9
10console.log('I now have this many beers: ' + getMoreBeers());
11
12// Output
13// I have this many beers: undefined
14// I now have this many beers: 25
Your Initial Guess vs Reality
Upon a first look, you might expect the output to show the number of beers as 5
and then 25
. However, the output is quite different. Let's explore why.
xxxxxxxxxx
var numOfBeers = 5;
function getMoreBeers() {
console.log('I have this many beers: ' + numOfBeers);
var numOfBeers = 25;
return numOfBeers;
}
console.log('I now have this many beers: ' + getMoreBeers());
// I have this many beers: undefined
// I now have this many beers: 25
Exploring Call Stack and Variable Hoisting: JS Execution
Console Log Order: The Call Stack in Action
The first thing to notice is the order in which the console log statements appear. The statement "I have this many beers" within the getMoreBeers
function is printed before "I now have this many beers."
1console.log('I have this many beers: ' + numOfBeers);
Why does this happen? It's all thanks to the call stack, a data structure that keeps track of function calls. The call stack operates based on a stack data structure, which follows a First-In-Last-Out (FILO) principle.
When this line of code runs:
1console.log('I now have this many beers: ' + getMoreBeers());
It becomes the first frame on the call stack.
Function Calls and the Call Stack
However, as soon as getMoreBeers()
is invoked, it gets pushed onto the top of the call stack, superseding the original console.log
statement.
1function getMoreBeers() {
2 console.log('I have this many beers: ' + numOfBeers);
3 var numOfBeers = 25;
4 return numOfBeers;
5}
Only after getMoreBeers()
fully executes, including its log statement, does the original console.log
statement get popped off the stack and executed.

Hoisting: The Underlying Phenomenon
Now, let's delve into hoisting, which explains the value undefined
in the output. In JavaScript, variable declarations are "hoisted" to the top of their respective scopes but remain uninitialized. This is why the numOfBeers
inside getMoreBeers()
is undefined
during the first console.log
.
1console.log('I have this many beers: ' + numOfBeers); // Output: undefined
Understanding the mechanics of the call stack and variable hoisting is crucial for both debugging and technical interviews.
Let's test your knowledge. Click the correct answer from the options.
What is a call stack?
Click the option that best answers the question.
- A data structure for telephone calls
- A stack that tracks method calls in a program
- An ordering mechanism
- A log of all the functions called
The Output Mystery
You've noticed that the output is intriguing. Despite having the variable numOfBeers
defined before the function, the console log within the function prints it as undefined
.
1// Output
2// I have this many beers: undefined
3// I now have this many beers: 25
The Role of Scoping and Hoisting
This oddity has to do with two core JavaScript concepts: scoping and hoisting.
Local vs Global Scope: Even though a variable with the same name exists in the global scope, JavaScript gives priority to the local scope within a function.
JAVASCRIPT1var numOfBeers = 5; // Global Scope
Hoisting in Action: In JavaScript, all variable declarations are "hoisted" to the top of their scope. This means that as soon as the function
getMoreBeers()
begins execution, JavaScript hoists the variablenumOfBeers
to the top of the function, but it remains uninitialized.JAVASCRIPT1function getMoreBeers() { 2 console.log('I have this many beers: ' + numOfBeers); // Local Scope, Hoisted but uninitialized 3 var numOfBeers = 25; // Local Scope, Initialized 4 return numOfBeers; 5}
The Undefined Log: When the
console.log
statement withingetMoreBeers()
runs, it finds the local, hoisted, but uninitializednumOfBeers
and prints it asundefined
.JAVASCRIPT1console.log('I have this many beers: ' + numOfBeers); // Output: undefined
Global Variable: A Common Misconception
Note that var numOfBeers = 5;
is a globally defined variable. Intuitively, one might think that this global variable should be accessible within the getMoreBeers
function.
1var numOfBeers = 5; // Globally Defined Variable
Hoisting: The Culprit
However, this expectation is thwarted by hoisting. Recall that hoisting moves variable declarations to the top of their current scope during the compilation phase.

var
vs const
and let
The hoisting behavior is specific to the var
keyword, making it distinct from const
and let
. During the lexical analysis step by JavaScript engines, the var numOfBeers
inside getMoreBeers
is hoisted to the top of the function's scope, even before the function executes.
1function getMoreBeers() {
2 // Hoisted but uninitialized
3 var numOfBeers;
4 console.log('I have this many beers: ' + numOfBeers); // Output: undefined
5 numOfBeers = 25; // Initialization
6 return numOfBeers;
7}
Breaking it Down: What Really Happens
So, when getMoreBeers
runs, JavaScript's hoisting places a new var numOfBeers;
at the top of the function, without initializing it. This local variable shadows the global one, and since it's uninitialized, the log statement shows undefined
.
xxxxxxxxxx
function getMoreBeers() {
// var numOfBeers;
console.log('I have this many beers: ' + numOfBeers);
var numOfBeers = 25;
return numOfBeers;
}
However, JavaScript only hoists declarations, not initializations. So the = 25
part is NOT hoisted alongside, thus numOfBeers
is undefined when console.log('I have this many beers: ' + numOfBeers);
is first run.

Complexity of Final Solution
O(1)
constant time & space complexity, this is a knowledge question!
One Pager Cheat Sheet
- We can observe that the
getMoreBeers()
function overwrites thenumOfBeers
variable, therefore when it is logged25
will be printed out, which can be explained by scope. Executing
this code willprint
theoutput
.- The order of the console log statements is determined by how the
call stack
works, with thegetMoreBeers()
function pushing the original statement onto the stack and executing first. - A call stack is a
data structure
that allows a program to keep track of function calls using thestack
(first in, last out) data structure. - The
variable
is returned as "undefined" in the log despite being clearly defined above the function. - We should
let
/const
and keep track of variable declarations to avoid unexpected results due tohoisting
. - The declarations of variables with the
var
keyword in JavaScript are hoisted, but not the initializations.
This is our final solution.
To visualize the solution and step through the below code, click Visualize the Solution on the right-side menu or the VISUALIZE button in Interactive Mode.
xxxxxxxxxx
# This is not applicable to Python
You're doing a wonderful job. Keep going!
If you had any problems with this tutorial, check out the main forum thread here.