클로저를 알기 위해서는 스코프의 개념을 먼저 이해해야 함
변수의 유효범위, 변수가 참조될 수 있는 범위
ex) 전역에 변수 선언 → 전역 변수 a는 어디서든지 참조할 수 있는 전역스코프를 가진다.
var 함수레벨 스코프 / let,const 블록레벨 스코프
var global = 'global'
function hi() {
var local = 'local'
console.log(global)
}
hi() // global
console.log(local) // Uncaught ReferenceError: local is not define
global 변수는 전역스코프를 가지기때문에 hi로 호출된 콘솔에 찍히지만,
local이라는 변수는 함수레벨 스코프를 가지기때문에
외부에서 참조하려고 하면 참조에러 발생
함수를 “어디에 선언하였는지” 에 따라 상위 스코프가 결정되는 것.
자바스크립트를 포함한 대부분의 프로그래밍 언어는 렉시컬 스코프를 따르며, 이를 정적 스코프(Static Scope)라고 부르기도 한다.
FYI : 동적 스코프는 랙시컬 스코프와 달리 함수를 “어디서 호출하였는지”에 따라 상위 스코프가 결정된다.
var x = 1;
function foo() {
var x = 10;
bar();
}
function bar() {
console.log(x);
}
foo(); // 1
bar(); // 1
bar에서 참조하는 x는 "상위 스코프" 가 무엇인지에 따라 결정됨
상위 스코프를 알려면 bar 함수가 "어디에 선언되었는지"를 봐야함
bar가 전역에 선언되었으므로 bar의 상위스코프 = 전역 스코프
그래서 상위스코프인 전역스코프에 선언된 x 변수를 참조함
자신이 생성될 때의 환경 (랙시컬 스코프)을 기억하는(=참조하는) 함수
밖에서 호출되어도 그 환경 (스코프)를 기억하여 접근하는 함수를 말한다.
const outerFunc = () => {
let x = 10;
// 이 애가 클로저
const innerFunc = (y) => {
x = x + y;
console.log(x);
}
return innerFunc;
}
const addFunc = outerFunc();
const addFunc2 = outerFunc()
addFunc(5);// 15
addFunc(10); // 25
addFunc(10); // 35
addFunc2(10) // 20
addFunc2(15) // 35
innerFunc의 x는 렉시컬스코프에 의해 outerFunc의 지역변수 x를 참조함
outerFunc은 const addFunc = outerFunc(); 에서 호출된 후 콜스택에서 제거되고, 가비지 컬렉터가 회수해야 할 것 같지만 , innerFunc에서 outerFunc의 x를 참조하기 때문에 회수되지 않는다.
외부함수가 종료되어도, 내부함수가 유효한 상태에서는 외부함수의 x 변수를 참조할 수 있다. 여기서 내부함수 = 클로저