Scope in JavaScript is important concept that handles variable availability. Understanding scope is a MUST if you are going to code in JavaScript
We will go step by step using simple examples, here is what you are going to learn
- Global scope
- Block scope
- Function scope
- Lexical scope
- Module scope
- Variable isolation
1. Global scope
As name itself is hinting, this scope is accessible from any inner scope, its the outermost scope.
//app.js
const settings = {...};
//settings can be used in any other scope inside your app
2. Block scope
A code block in JavaScript ( if condition, loop, etc ) defines its own scope, but only if you are using let
and const
variable declarations introduced with ES6
if(true){
let blog = 'hashnode';
console.log(blog); // 'hashnode'
var state = 'awesome';
console.log(state); // 'awesome'
}
console.log(blog); // Reference Error
console.log(state); // 'awesome'
blog
is defined in "if block" scope and its only accessible there.
Difference with var
is that var
declarations are not block scoped ( they are function / module scoped, more on that further down in post )
3. Function scope
Unlike block scope, function scope will "hold" all three variable declarations var
, let
and const
function writeBlogPost(){
const postID = 113312;
let postMeta = 'very important meta data';
var postTitle = 'A Simple Explanation of JavaScript Scope';
console.log(postID); // 113312
console.log(postMeta); // 'very important meta data'
console.log(postTitle); // 'A Simple Explanation of JavaScript Scope'
}
writeBlogPost();
console.log(postID); // Reference Error
console.log(postMeta); // Reference Error
console.log(postTitle); // Reference Error
Same way as function body creates scope for var
, let
and const
it does for function declarations also
function writeBlogPost(){
//..
function checkSpelling(){ ... }
console.log(checkSpelling()); // some output
}
console.log(checkSpelling()); // Reference Error
Now let's see how variables are shared within nested functions
4. Lexical scope
Let's start with our two functions
function writeBlogPost(){
// outer scope
let postTitle = 'A Simple Explanation of JavaScript Scope';
console.log(status); // Reference Error
function checkSpelling(){
// inner scope
let status = 'ok';
console.log(postTitle); // A Simple Explanation of JavaScript Scope';
}
return checkSpelling;
}
var write = writeBlogPost();
write();
From code we can see that inner function checkSpelling
can see outer function writeBlogPost
variable postTitle
but same is not true other way around, outer function writeBlogPost
can't see inner function checkSpelling
variable status
.
Why is this and how this works ? Well easiest real life reference I could think of would be 1 way mirror, you can only see looking from one side.
If we had multiple scopes / functions it would look something like this layered up
//mirror direction
--->
innermost Function -> inner Function -> outermost Function -> global
But this is not whole story,
If you take a look at our functions one more time you will see that outer function returns with checkSpelling
, essentially meaning that function is "done" and scope with variables and their data should be gone ?
Well yes, you would be right, this is where Closures find their use.
MDN "definition"
“A closure is a special kind of object that combines two things: a function, and the environment in which that function was created. The environment consists of any local variables that were in-scope at the time that the closure was created.”
Since this is material for whole another post I will leave you off there, drop by later I will go over this in detail.
5. Module scope
Let's create our simple module blogData
,
const userID = 93939;
/*
some operations with user id.
.
.
*/
Now let's try to import this module and use userID
import './blogData';
console.log(userID) // Reference Error
Ok so what happened ?
userID
is not accessible outside of blogData
module ( unless explicitly exported using export
)
Module scope makes the module encapsulated, so every private variable ( variable that's not exported ) remains an internal detail. Module scope protects these variables from being accessed from the outside.
6. Variable isolation
This is real saver, allows us to reuse common variable names.
In short let
and const
are block scoped as I wrote earlier meaning we can use identical variable names without conflict.
This is how it looks:
function getBlogHearts(){
let count = 10;
console.log(count) // 10
}
function getBlogViews(){
let count = 55;
console.log(count) // 55
}
Both have count
variable and we can use it without problem.
Takeaways
- Scope is a policy that manages variable availability, variable defined within a scope is accessible only in that scope.
- Scopes are created by code blocks, functions and modules.
- Scopes can be nested, inner function has access to outer function data/variables.
const
andlet
are scoped by code blocks whilevar
is scoped only by function and modules.
Check out my other articles on JS: