스코프(Scope)는 변수와 함수에 접근할 수 있는 유효 범위를 의미
코드가 실행될 때, 자바스크립트 엔진은 이 스코프를 기준으로 특정 변수에 접근할 수 있는지 없는지를 결정한다.
JS에서 스코프는 기본적으로 함수가 선언될 때(Lexical Scoping) 결정되지만, 실제 스코프가 활성화되고 변수가 채워지는 것은 함수가 호출될 때이다.
// 전역 스코프
const globalVar = '전역 변수';
function outerFunc() {
// 외부 함수 스코프
const outerVar = '외부 함수 변수';
function innerFunc() {
// 내부 함수 스코프
const innerVar = '내부 함수 변수';
console.log(globalVar); // 접근 가능
console.log(outerVar); // 접근 가능
console.log(innerVar); // 접근 가능
}
innerFunc();
}
outerFunc();
outerFunc가 호출될 때 outerFunc의 스코프가 생성되고, 그 안에서 innerFunc가 호출될 때 innerFunc의 스코프가 생성된다. (중첩된 구조)
스코프 체인(Scope Chain)은 자바스크립트 엔진이 변수를 찾기 위해 현재 스코프에서부터 상위 스코프로 차례대로 거슬러 올라가는 과정
변수를 사용하면, 엔진은 다음과 같은 순서로 변수를 찾는다.
innerFunc 내부에서 console.log(outerVar)를 실행할 때의 과정
클로저(Closure)는 함수가 선언될 때의 렉시컬 환경(Lexical Environment)을 기억하여, 함수가 자신의 스코프 밖에서 호출될 때에도 그 환경에 접근할 수 있게 해주는 현상이다.
즉, 함수는 자신이 선언된 스코프를 절대 잊지 않는다.
function createCounter() {
let count = 0; // 외부 함수의 변수 (자유 변수)
// 이 내부 함수가 바로 클로저
return function() {
count++;
console.log(count);
};
}
// counter 함수는 createCounter의 실행 컨텍스트(스코프)를 기억한다.
const counter = createCounter();
// createCounter 함수는 이미 실행이 끝나 사라졌지만,
// counter 함수는 자신이 태어난 환경의 변수 'count'에 여전히 접근 가능함
counter(); // 1
counter(); // 2
counter(); // 3
이처럼 클로저는 데이터를 특정 함수와 묶어 외부로부터의 접근을 제한하고, 상태를 안전하게 유지하고자 할 때 매우 유용하게 사용된다.
이를 정보 은닉(Information Hiding) 이라고 함