Scope and Closures
Chapter 9 • Intermediate
Scope and Closures
Understanding scope and closures is crucial for writing effective JavaScript code. Scope determines where variables can be accessed, and closures allow functions to "remember" their lexical environment.
Scope
Scope refers to the visibility and accessibility of variables in different parts of your code.
Global Scope
Variables declared outside any function are in global scope:
let globalVar = 'I am global';
function example() {
console.log(globalVar); // Can access global variables
}
Function Scope
Variables declared inside a function are only accessible within that function:
function example() {
let localVar = 'I am local';
console.log(localVar); // Works
}
console.log(localVar); // Error: localVar is not defined
Block Scope (let and const)
Variables declared with let and const are block-scoped:
if (true) {
let blockVar = 'I am block-scoped';
const anotherBlockVar = 'Me too';
}
console.log(blockVar); // Error: blockVar is not defined
Closures
A closure is a function that has access to variables in its outer (enclosing) scope even after the outer function has returned.
Basic Closure Example
function outerFunction(x) {
// Outer function's variable
let outerVariable = x;
// Inner function (closure)
function innerFunction(y) {
return outerVariable + y;
}
return innerFunction;
}
let closure = outerFunction(10);
console.log(closure(5)); // 15
Practical Closure Example
function createCounter() {
let count = 0;
return {
increment: function() {
count++;
return count;
},
decrement: function() {
count--;
return count;
},
getCount: function() {
return count;
}
};
}
let counter = createCounter();
console.log(counter.increment()); // 1
console.log(counter.increment()); // 2
console.log(counter.getCount()); // 2
The this Keyword
The this keyword refers to the object that is executing the current function. Its value depends on how the function is called.
this in Different Contexts
let person = {
name: 'John',
greet: function() {
console.log('Hello, I am ' + this.name);
}
};
person.greet(); // 'Hello, I am John'
let greetFunction = person.greet;
greetFunction(); // 'Hello, I am undefined' (in strict mode)
Binding this
let person = {
name: 'John',
greet: function() {
console.log('Hello, I am ' + this.name);
}
};
let boundGreet = person.greet.bind(person);
boundGreet(); // 'Hello, I am John'
Hands-on Examples
Scope Example
let globalVar = 'Global variable';
function outerFunction() {
let outerVar = 'Outer variable';
function innerFunction() {
let innerVar = 'Inner variable';
console.log('Inner can access:', innerVar);
console.log('Inner can access:', outerVar);
console.log('Inner can access:', globalVar);
}
innerFunction();
console.log('Outer can access:', outerVar);
console.log('Outer can access:', globalVar);
// console.log(innerVar); // Error: innerVar is not defined
}
outerFunction();
console.log('Global can access:', globalVar);Inner functions can access variables from outer scopes, but outer functions cannot access variables from inner scopes.