자바스크립트는 렉시컬 스코프(lexical scope) 를 따른다.
즉, 코드가 작성된 '위치'를 기준으로 변수가 어디까지 보이는지가 결정된다.
보통은 함수 안의 변수는 함수 밖에서 접근할 수 없다.
함수가 실행되고 끝나면 내부 변수들은 사라진다. 더이상 참조하지 않으니 GC가 치우는 것이다.
그런데 클로저란?
어떤 함수가 자기 바깥(상위)의 변수를 기억하고,
그 함수가 실행될 때 계속 접근할 수 있는 현상을 말한다.
즉, 함수가 종료되어도 그 함수가 '참조하고 있던 스코프'를 붙잡아 두는 것.
function outer() {
let count = 0; // 바깥 변수
function inner() {
count++;
return count;
}
return inner; // inner 함수를 밖으로 내보냄
}
const counter = outer();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
outer()가 실행되고 끝났는데도 count가 사라지지 않고,
inner 함수가 그 값을 계속 기억하고 있다. 이게 클로저!
이게 가능한 이유는 함수가 생성될 때의 렉시컬 스코프(lexical scope)를 기억하고, 해당 스코프의 변수에 계속 접근할 수 있기 때문에 메모리에 유지하는 것이다. 변수에 참조하니 GC가 치우지 않는다.
👉 결론:
클로저는 '함수와 그 함수가 선언될 당시의 스코프를 묶어서 기억하는 것'
→ 그래서 함수 밖에서도 함수 안 변수를 계속 활용할 수 있다.
😨 아니 그냥 전역 변수 쓰면 되는 거 아냐?
아니다! 클로저를 쓰면 데이터 캡슐화/은닉이 가능하다. 외부에서 함부로 조작이 불가능하다. 그리고 여러 개의 독립된 상태를 만들 수 있다.
function outer() {
let count = 0; // 바깥 변수
function inner() {
count++;
return count;
}
return inner; // inner 함수를 밖으로 내보냄
}
const counter1 = outer();
const counter2 = outer();
const counter3 = outer();
console.log(counter1()); // 1
console.log(counter2()); // 1
console.log(counter3()); // 1
전역 변수는 말 그대로 전역 변수라서 여기저기서 막 참조가능..