In programming, the concepts of lexical and in-memory scopes are two important tenets used to determine where a variable can be used in a program. Every programming language has its own scoping rules – this article covers JavaScript’s rules.
Lexical Scope
A very efficient definition of scope is laid out by Oluwatobi Sofela:
Scope refers to the area where an item (such as a function or variable) is visible and accessible to other code.
An item is said to be lexically scoped when it's first declared. In other words, its accessibility is created at the same time it is created. Lexical scoping can help to avoid naming conflicts, and it keeps variables localized to where they are needed.
var hasLexicalScope; // a variable
function example(){
console.log('I have lexical scope as well')
} // a function declaration
Within the category of lexical scope, there are three sub-categories:
- block scope (think, a conditional or a loop)
- function scope
- global scope
Variables defined in either a block of code or a function declaration can only be used in that block or function, because that's the area where they were created. Any attempt otherwise, will result in a reference error.
Conversely, if a variable is not block- or function-scoped, it has global scope -- it is accessible from anywhere in its program.
let isGloballyScoped = "example";
console.log(isGloballyScoped); // prints example
function isFunctionScoped() {
let message = "I can only be accessed from inside my
function !";
}
console.log(message); // prints Reference Error: message is
not defined
if (1 === 2) {
var isBlockScoped = "I can only be accessed from inside
my code block!";
}
console.log(isBlockScoped); // prints Reference Error:
isBlockScoped is not defined
In-Memory Scope
In-memory scope refers to the availability of a variable or function while it's being executed. This means, that when a function or a variable is running, its information is temporarily stored in memory, in a structure referred to as an execution context. In-memory scoping can make it easier to share data between different parts of the code.
If you've heard the term call-stack, you already known what an execution context is!
A variable can be accessed from any part of the code that is called by the same execution context. It's important to note that every time a function is called, a new execution context is created.
function outer() {
const message = "Hello, world!";
function inner() {
console.log(message); // This will also log "Hello, world!"
}
setTimeout(inner, 1000);
}
outer();
In this example, the variable message
is still declared inside the outer
function, but it is also accessible inside the inner
function, which is called by the setTimeout
function after a delay of 1000 milliseconds. Since inner
is called by the same call stack as outer
, it can access the message
variable even though it is not in its lexical scope.
To sum up, the main difference between lexical and in-memory scope is that lexical scoping is determined at compile-time and remains fixed at runtime, whereas in-memory scoping is determined at runtime and can be changed during the execution of the program.
I hope this article has provided you clarity on this crucial topic in computing, & thank you for reading!
Top comments (0)