In our starter files, open the index.html page from this lessons folder:
09.Scope-Hoisting-Closures > 02.Nesting-scope
So far, we discovered scope only appears to work one way, from outside to inside. Variables declared at the top, global level, are available inside of other functions or blocks.
We can carry on by nesting other statements inside of others, and the scope continues in the same way. Access is passed down to each level, yet new variables declared inside of new blocks are restricted, they are effectively not passed back up to outer levels.
This scope nesting is referred to as lexical scope in JavaScript and many other languages.
To begin, we have the same setup as previously used:
var score = 0;
function updateScore() {
score++;
var bonus = 10;
console.log(score + bonus);
}
updateScore();
First, change the console log so we know where we are because we are going to be extending this code:
console.log('inside function’);
Then still inside the function, nest another block, such as an if
statement:
function updateScore() {
score++;
var bonus = 10;
console.log('inside function');
// create if statement inside of function
if (bonus) {
console.log('inside if statement: ' + bonus);
}
}
This if
statement is trying to access the bonus
variable from the outer scope, what do you think will happen?
This will work fine. Nested statement blocks can access variables from the outer scope, but what about the other way around? Let's take a look:
function updateScore() {
score++;
var bonus = 10;
// 2. try to log bonus2 from a level above
console.log('inside function ' + bonus2);
if (bonus) {
// 1. create new nested var
var bonus2 = 20;
console.log('inside if statement: ' + bonus);
}
}
The result will be undefined
, meaning this does not work the other way around. We get undefined
meaning the variable exists, but it is assigned an undefined
value.
Side note: If bonus2
was declared with let
or const
, it would throw an error rather than having the undefined
value, but more on this soon.
The nesting can also continue as deep as we want to go, let’s try another block statement, the while
loop. This also has its own curly braces to enclose the code, and create a new, inner scope.
Remove the bonus2 variable, along with the console log referring to this variable.
Add the while
loop inside the if
statement:
function updateScore() {
score++;
var bonus = 10;
if (bonus) {
console.log("inside if statement: " + bonus);
var numbers = [1, 5, 8, 2];
var i = 0;
// create while loop:
while (i < numbers.length) {
console.log(numbers[i]);
i++;
}
}
}
This works fine, the console will display the numbers
from the outer block. And you can probably guess what happens if we create a new variable in the while loop, and access it on an outer level:
function updateScore() {
score++;
var bonus = 10;
// 2. Log bonus3 in outer scope
console.log("inside function " + bonus3);
if (bonus) {
console.log("inside if statement: " + bonus);
var numbers = [1, 5, 8, 2];
var i = 0;
while (i < numbers.length) {
// 1. create new variable inside while loop
var bonus3 = 30;
console.log(bonus);
i++;
}
}
}
The result is undefined once again since we are trying to access a nested variable from an outer scope.