#003 JavaScript with Dimos: Scope Explained
Hey there 👋 I am Dimos, a senior software engineer and software architect at arconsis. From time to time, I publish articles into the series “JavaScript with Dimos”, where I am trying to analyze a JavaScript topic and to focus on the core concepts of JavaScript.
Scope defines variable’s accessibility (visibility). If we would like to code in JavaScript, then understanding the variable’s scope is mandatory. JavaScript has the 2 following scope types:
- Global scope
- Local scope:
a) Function scope
b) Lexical scope
c) Block scope
d) Module scope
Global Scope
The outmost scope is referred to as global scope. Any variable declared outside of a function is a global variable, which can be accessed from any other scope.
For example window and document are global variables supplied by the browser.
const animal = "cat";function myFunction() {
console.log(animal);
}
myFunction(); // output: cat
In the above code block, the variable animal is declared at the top of the program, therefore, is a global variable. This means that it can be used anywhere in the program. Hence, animal can be accessed inside any function, e.g. in myFunction().
When we assign a value to a variable that has not been declared (we forgot to add var / const / let keyword), it will automatically become a global variable.
function myFunction() {
vehicle = "car"; // vehicle is considered as global variable
}myFunction();
console.log(vehicle); // output: car
Note: It is preferable to avoid creating, using global variables (considered as anti-pattern), because the value of a global variable can change in different parts in the program and can lead to unexpected results. We should always have strict mode enabled (in ES5, the Strict Mode is optional but in ES6, it’s needed for many ES6 features).
'use strict';
function myFunction() {
vehicle = "car"; // vehicle is considered as global variable
}myFunction();
console.log(vehicle); // Uncaught ReferenceError: assignment to undeclared variable vehicle
In the above program, we used ‘use strict’ which will execute code block in ‘strict mode’. Hence, when we try to use a variable animal (which is not declared), we get a ReferenceError, as in strict mode, we cannot use the variable without declaring them.
Function scope
Each function creates its own new scope. Variables defined inside a function can’t be accessed from anywhere outside the function, since the variable is defined only in the scope of the function. A function, on the other hand, can access all variables and functions defined within the scope in which it was defined.
When declared inside a function, variables declared with var, let and const are quite similar, as they are function-scoped
function myFunction() {
const animal = "cat";
console.log(animal);
}myFunction(); // output: cat
console.log(animal); // Uncaught ReferenceError: animal is not defined
In the above program, the variable animal can be accessed only inside the function myFunction(), as is function-scoped. Therefore, when we try to access variable animal outside of the function, an error occurs.
Lexical scope
The ability for a function scope to access variables from the parent scope is known as lexical scope (or static scope). As a result, variable accessibility is determined statically by the position of variables within nested function scopes. Therefore, a nested inner function (closure) can access the scope of an outer function.
function outerFunc() {
// the outer scope
const animal = "cat";
function innerFunc() {
// the inner scope
console.log(animal); // output: cat
}
return innerFunc;
}outerFunc()();
In the above program, we have 2 functions the outerFunc() and a nested one called innerFunc(). As we can see the innerFunc() (because of lexical scoping) can access animal animal variable which is function-scoped to outerFunc(). Hence, in the above example, the lexical scope of innerFunc() consists of the scope of outerFunc().
Block scope
The ES6 introduced two new JavaScript keywords: let and const , which provide Block Scope. As a result, a variable declared using let or const can only be accessed within the block in which it was declared. A variable declared using var, on the other hand, stays function-scoped.
The code block of if, for, while statements also create a block scope. Hence a variable declared inside {…} can not be accessed outside the block.
for (const animal of ['cat', 'dog', 'wolf']) {
// "for" block scope
const message = 'Hi';
console.log(animal); // output: 'cat', 'dog', 'wolf'
console.log(message); // output: 'Hi', 'Hi', 'Hi'
}console.log(animal); // Uncaught ReferenceError: color is not defined
console.log(message); // Uncaught ReferenceError: message is not defined
Another one example:
function myFunction() {
const animal = "cat";
if (true) {
var car1 = "porsche";
const car2 = "opel";
let car3 = "volvo";
console.log(car1); // output: porsche
console.log(car2); // output: opel
console.log(car3); // output: volvo
}
console.log(animal); // output: cat
console.log(car1); // output: porsche
console.log(car2); // Uncaught ReferenceError: car2 is not defined
console.log(car3); // Uncaught ReferenceError: car3 is not defined
}
myFunction();In the above program, variable
animalis a local variable (function-scoped) and can be accessed only inside the functionmyFunction().car1is declared asvarfor this reason is considered as function-scoped variable and can be accessed only inside the functionmyFunction()car2andcar3variables are declared usingconstandlet, hence are considered as block-scoped and can be accessed only inside theifstatement block.
Module scope
The ES6 module also creates a scope for variables, functions, classes. Before ES6 modules, every variable declared outside any function was a global variable. Now, if we declare a variable inside an ES6 module is hidden and not available to other modules unless it is explicitly exported.
Let’s try to create a module called animal which has a declared variable.
// "animal" module scope in animal.js file
const cat = "cat";
console.log(cat); // output: cat
// Usage of catLet’s try to import above module:
import './animal';
console.log(cat); // Uncaught ReferenceError: cat is not definedThe variable cat is not accessible outside of animal module (unless explicitly exported using export). The module scope makes the module encapsulated and every variable (that’s not exported) remains as “private”.
Get Dimosthenis Botsaris’s stories in your inbox
Join Medium for free to get updates from this writer.
Let’s now try to explicitly export cat from animal module.
// "animal" module scope in animal.js file
const cat = "cat";
console.log(cat); // output: cat// export cat variable explicitly
export { cat };
and now import it to another JS file:
import { cat } from './animal.js';console.log(cat); // output: cat
Those are all the scopes available in JavaScript. Meanwhile, please feel free to post any questions, comments, or feedback in the comment section below.
Follow on Twitter here!
Follow on Github here!
Further Reading
- https://www.tutorialsteacher.com/javascript/scope-in-javascript
- https://dmitripavlutin.com/javascript-scope/
- https://www.w3schools.com/JS//js_scope.asp
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions#function_scope
- https://www.programiz.com/javascript/variable-scope
- https://www.educative.io/edpresso/lexical-scope-in-javascript
- https://www.freecodecamp.org/news/an-introduction-to-scope-in-javascript-cbd957022652/










