2. Scope Chain & Closure
1. 스코프 체인(Scope Chain)
스코프 체인은 중첩된 스코프에서 변수 검색이 이루어지는 과정이다.
자바스크립트는 변수를 찾을 때 현재 스코프 → 상위 스코프 → 전역 스코프 순서로 검색한다.
만약 변수명이 겹치면 가장 가까운 스코프에서 찾은 변수를 사용한다.
let globalVar = "Global";
function outer() {
let outerVar = "Outer";
function inner() {
let innerVar = "Inner";
console.log(innerVar); // "Inner" (현재 스코프에서 찾음)
console.log(outerVar); // "Outer" (상위 스코프에서 찾음)
console.log(globalVar); // "Global" (전역 스코프에서 찾음)
}
inner();
}
outer();
▶ 스코프 체인은 중첩된 함수가 자신의 스코프뿐만 아니라 상위 스코프를 기억하기 때문에 가능하다.
▶ 자바스크립트는 항상 렉시컬(정적) 스코프를 사용하므로 함수가 선언된 위치에 따라 스코프가 결정된다.
2. 클로저(Closure)
클로저는 함수와 해당 함수가 선언될 때의 스코프를 기억하는 객체이다.
클로저는 외부 함수가 실행을 끝내도, 내부 함수가 외부 함수의 변수에 접근할 수 있도록 한다.
function createCounter() {
let count = 0; // 이 변수는 클로저로 내부 함수에서 기억됩니다.
return function () {
count++; // 내부 함수에서 외부 함수의 변수에 접근
console.log(count);
};
}
const counter = createCounter();
counter(); // 1
counter(); // 2
counter(); // 3
▶ 클로저는 데이터 캡슐화를 가능하게 한다.
▶ 외부 변수(count)는 createCounter 호출이 끝난 후에도 사라지지 않고 메모리에 유지된다.
▶ 이런 특성을 활용해 상태를 저장하는 함수를 만들 수 있다.
3. 함수 스코프와 블록 스코프의 상호작용
ES6 이전에는 변수 선언에 var만 사용되었고, 이는 함수 스코프만 가졌다. 하지만 ES6 이후에는 let과 const가 도입되어 블록 스코프를 사용할 수 있게 되었다.
function testVar() {
if (true) {
var x = 10;
}
console.log(x); // 10 (var는 함수 스코프)
}
function testLet() {
if (true) {
let y = 20;
}
console.log(y); // Error: y is not defined (let은 블록 스코프)
}
testVar();
testLet();
▶var는 함수 스코프만 갖기 때문에 의도치 않은 스코프 오염이 발생할 수 있다.
▶let과 const는 블록 스코프를 가지므로 더 안전하게 변수 관리를 할 수 있다.
4. 클로저와 메모리 관리
클로저는 잘못 사용하면 메모리 누수가 발생할 수 있다. 클로저를 사용하는 함수가 더 이상 필요 없을 때 참조를 해제해 메모리 누수를 방지해야 됨.
function createResource() {
let resource = "Heavy Resource";
return function () {
console.log(resource);
};
}
const useResource = createResource();
useResource(); // "Heavy Resource"
// 클로저를 더 이상 사용하지 않는다면 null로 참조 해제
useResource = null;
▶ 클로저는 외부 변수에 대한 참조를 유지하는 특성을 가지므로 더 이상 사용할 필요 없는 경우 참조를 해제해야 메모리가 회수된다.
▶ 자바스크립트의 가비지 컬렉터가 자동으로 이를 처리하지만, 명시적으로 관리해 주는 것이 좋다.
5. 즉시 실행 함수(IIFE)와 스코프
IIFE(Immediately Invoked Function Expression)는 선언과 동시에 실행되는 함수입니다. 이 방식은 변수를 전역 스코프에 오염시키지 않고 코드를 캡슐화할 때 유용합니다.
(function () {
let secret = "This is private";
console.log(secret); // "This is private"
})();
console.log(secret); // Error: secret is not defined
IIFE는 함수 내부에 변수를 캡슐화하여 전역 변수 오염을 방지한다.
ES6 이후에는 블록 스코프(let, const)를 선호하는 경향이 있지만, 여전히 유용하다.
스코프 체인: 변수를 찾을 때 현재 스코프 → 상위 스코프 → 전역 스코프 순으로 검색.
클로저: 외부 함수의 변수 상태를 기억하며, 데이터 캡슐화와 상태 저장에 유용.
블록 스코프와 함수 스코프: var와 let/const의 스코프 동작 차이가 있음.
메모리 관리: 클로저는 강력하지만, 적절히 관리하지 않으면 메모리 누수가 발생할 수 있음. (사용 후 해제하기)
IIFE: 전역 변수 오염을 방지하는 방법
클로저를 활용한 이벤트 핸들러 관리
클로저를 활용하여 동적으로 이벤트 핸들러를 추가하거나 데이터를 캡슐화할 수 있다.
function createEventHandlers(elements) {
elements.forEach((element, index) => {
element.addEventListener("click", () => {
console.log(`Element ${index} clicked`);
});
});
}
const buttons = document.querySelectorAll("button");
createEventHandlers(button
No Comments