What is scope?
Scope in JavaScript is similar to an actual scope in real life. Whenever you look through a scope, you can only see a certain part of what's around you. Similarly, scope in JavaScript simply refers to the current context of the code; it determines where variables can be accessed. The two main types of scope are global and local. A locally-scoped variable can either be function scope or block scope, but that'll be covered later. For now, let's look at global and local scope.
Global scope
// script.js
var msg = 'hello!';
function sayHi() {
}
...here, the variable msg
is declared at the top of the script, outside of any functions.
Because of this, the variable is globally-scoped. When a variable is in the global scope, it can be accessed from anywhere,
including inside of functions...
// script.js
var msg = 'hello!';
function sayHi() {
return msg;
}
console.log(sayHi()); // hello!
...as you can see, the function returns the value without any issues. This is where global scope differentiates from local scope.
Local scope
Unlike global scope, local scope works a little differently. Using the same example, let's move the variable inside the function:
// script.js
function sayHi() {
var msg = 'hello!';
return msg;
}
console.log(sayHi()); // hello!
...everything works the same, but now the msg
variable is in the local scope. This
means the variable can only be accessed within that function. If we try accessing the variable outside the
sayHi()
function, it'll throw an error...
// script.js
function sayHi() {
var msg = 'hello!';
}
console.log(msg); // UncaughtReferenceError: msg is not defined
...since this produces an error, you may be inclined to believe this is bad, so you might decide to declare everything globally. Well, believe it or not, you WANT these type of errors.
Declaring every single variable globally isn't the best idea. For one, it uses up more resources, which can throttle the performance of bigger applications. Additionally, it doesn't make a lot of sense; if you need to use a variable inside a function, declare it inside that function — why would you declare it outside?
Function scope and block scope
Now that we covered global scope and local scope, we can talk about function scope and block scope, which are two types of local scope. To put it simply, a variable is in function scope when it's declared inside a function:
// script.js
function sayHi() {
var msg = 'hello!';
}
...simple enough, right? On the other hand, if you declare a variable in something like a conditional statement or loop, then it's considered to be in block scope...
// script.js
if (true) {
var msg = 'hello!';
}
...since both of these examples are locally-scoped, both should throw an error if
msg
is accessed from the outside, right? Let's find out...
// script.js
function sayHi() {
var msg = 'hello!';
}
console.log(msg); // UncaughtReferenceError: msg is not defined
if (true) {
var msg = 'hello!';
}
console.log(msg); // hello!
...wait a second, how come the conditional statement doesn't throw an error, despite msg
being locally-scoped? The reason for this is hoisting. Hoisting is a whole different topic that I'll cover in a separate
article; for now, you just need to know that we don't want this type of behavior. We want block scope variables to behave the
same way as function scope variables, being accessible only from within the curly braces. The solution to this? The
let
and const
keywords.
let keyword
Let's try running the conditional statement from earlier again, this time using the let
keyword instead of var
:
// script.js
if (true) {
let msg = 'hello!';
}
console.log(msg); // UncaughtReferenceError: msg is not defined
...awesome! Now it behaves like a true local scope variable. let
is essentially
the replacement for var
. There's no reason to declare variables with the
var
keyword anymore — it can cause a lot of unwanted bugs and it's
a syntax that's long outdated. Avoid using var
and opt for let
or const
instead, which we're about to cover.
const keyword
Along with the addition of the let
keyword, const
was also introduced to JavaScript.
const
is a way to assign an identifier that won't be changed, a "constant". Whereas variables
declared with the let
keyword can be reassigned, variables declared with const
cannot. Here's an example:
let age = 12;
age = 14;
console.log(age); // 14
const ANIMAL = 'dog';
ANIMAL = 'cat'; // UncaughtTypeError: Assignment to constant variable
...age
is declared with the let
keyword, therefore it can be reassigned without
a problem. If we try to reassign ANIMAL
, it'll throw an error. Typically, it's best practice to declare
const
variables using all-uppercase letters.
One final thing to note is that unlike the var
keyword (which you shouldn't use),
neither let
or const
can be re-declared:
var msg = 'hello';
var msg = 'bye';
console.log(msg);
// bye
let age = 12;
let age = 14;
// UncaughtSyntaxError: Identifier 'age' has already been declared
const ANIMAL = 'dog';
const ANIMAL = 'cat';
// UncaughtSyntaxError: Identifier 'ANIMAL' has already been declared
...to summarize, use let
for identifiers that might change, and const
for identifiers that'll remain constant. Avoid using var
at all costs!