const
x
=
3
;
console
.
log
(
x
);
// logs "3"
}
console
.
log
(
typeof
x
);
// logs "undefined"; x out of scope
It’s easy enough to understand here that there are two distinct variables, both named
x
in different scopes. Now consider what happens when the scopes are nested:
{
// outer block
let
x
=
'blue'
;
console
.
log
(
x
);
// logs "blue"
{
// inner block
let
x
=
3
;
console
.
log
(
x
);
// logs "3"
}
console
.
log
(
x
);
// logs "blue"
}
console
.
log
(
typeof
x
);
// logs "undefined"; x out of scope
This example demonstrates variable masking. In the inner block,
x
is a distinct vari‐
able from the outer block (with the same name), which in effect masks (or hides) the
x
that’s defined in the outer scope.
What’s important to understand here is that, when execution enters the inner block,
and a new variable
x
is defined, both variables are in scope; we simply have no way of
accessing the variable in the outer scope (because it has the same name). Contrast this
with the previous example where one
x
came into scope and then exited scope before
the second variable named
x
did the same.
To drive this point home, consider this example:
{
// outer block
let
x
=
{
color
:
"blue"
};
let
y
=
x
;
// y and x refer to the same object
let
z
=
3
;
{
// inner block
let
x
=
5
;
// outer x now masked
console
.
log
(
x
);
// logs 5
console
.
log
(
y
.
color
);
// logs "blue"; object pointed to by
// y (and x in the outer scope) is
// still in scope
y
.
color
=
"red"
;
console
.
log
(
z
);
// logs 3; z has not been masked
}
console
.
log
(
x
.
color
);
// logs "red"; object modified in
// inner scope
console
.
log
(
y
.
color
);
// logs "red"; x and y point to the
// same object
122 | Chapter 7: Scope