Javascript Closures and Scope

Scope:

  • Global Scope: Variables declared outside any function or block are accessible from anywhere in the code.
  • Local (Function) Scope: Variables declared inside a function are accessible only within that function.
  • Block Scope: Variables declared using let and const are block-scoped to the nearest curly braces {}.

Closures

A closure is formed when a function is defined within another function and the inner function has access to the variables of its outer (enclosing) function, even after the outer function has finished executing. Closures allow you to capture the state of the outer function at the time the inner function is defined, preserving this state for future use.

Closures are created when:

  • An inner function is defined within an outer function.
  • The inner function references variables from the outer function’s scope.
  • Here’s a more in-depth example to illustrate closures:
function outer(outerParam) {
var outerVar = 'I am from outer';

function inner(innerParam) {
console.log(outerParam + ' ' + outerVar + ' ' + innerParam);
}

return inner;
}

var innerFunc = outer('Hello');
innerFunc('World'); // Prints: Hello I am from outer World

In this example, the inner function is a closure because it captures the variables outerParam and outerVar from the outer function’s scope. Even after outer has finished executing and its scope theoretically disappears, the inner function still has access to those variables.

Lexical Scoping:

Lexical scoping (also known as static scoping) is the way in which variables are resolved in a programming language. In JavaScript, lexical scoping means that the scope of a variable is determined by its position within the source code’s nested function structure.

Variables are looked up in the scope hierarchy based on where they are physically located in the code, regardless of where they are actually executed. This is in contrast to dynamic scoping, where variable scope is determined by the current context of the program.

Here’s an example illustrating lexical scoping:

var globalVar = 'I am global';

function outer() {
var outerVar = 'I am outer';

function inner() {
console.log(globalVar); // Accessible due to lexical scoping
console.log(outerVar); // Accessible due to lexical scoping
}

return inner;
}

var innerFunc = outer();
innerFunc();

In this example, both the inner function and the outer function have access to the globalVar variable due to lexical scoping. However, only the inner function can access the outerVar variable since it’s within the same scope level.

Understanding lexical scoping is crucial for understanding how closures work because closures rely on capturing the scope chain at the time of function definition.

Scope Chain:

The scope chain is the order in which JavaScript looks up variables in nested functions to find their values. When a variable is referenced, JavaScript first searches for it in the current function’s scope, then in the outer function’s scope, and so on until it reaches the global scope. This chain of nested scopes is called the scope chain.

Here’s an example to illustrate the scope chain:

var globalVar = 'Global';

function outer() {
var outerVar = 'Outer';

function inner() {
var innerVar = 'Inner';
console.log(innerVar); // Searches inner scope
console.log(outerVar); // Searches outer scope
console.log(globalVar); // Searches global scope
}

inner();
}

outer();

In this example, the inner function’s scope chain is: innerVar -> outerVar -> globalVar.

Variable Hoisting:

Variable hoisting is a JavaScript behavior where variable declarations (but not assignments) are moved to the top of their containing function or block before the code is executed. This means you can access a variable before it’s formally declared in the code.

However, the variable is hoisted, not its value. So, if you access a variable before it’s assigned a value, you’ll get undefined.

Here’s an example of variable hoisting:

console.log(x); // Outputs: undefined
var x = 10;

What actually happens is this:

var x;
console.log(x); // Outputs: undefined
x = 10;

Function declarations are also hoisted in their entirety, which means you can call a function before its declaration in the code:

hoistedFunction(); // Outputs: "This is a hoisted function."

function hoistedFunction() {
console.log("This is a hoisted function.");
}

However, variable assignments are not hoisted. Only the declaration part is hoisted. This is why you can’t access the value of a variable before its assignment.

You can also discover a lot about Javascript by exploring different topics.

Note: We welcome your feedback at Easy coding School. Please don’t hesitate to share your suggestions or any issues you might have with the article!

Leave a Reply

Your email address will not be published. Required fields are marked *