[javascript] 클로저 / 스코프
스코프
참조 대상 식별자를 찾아내기 위한 규칙
변수 / 함수의 유효범위를 뜻함
전역 스코프 (Global scope) : 스크립트 전체에서 참조되는 것을 의미하며, 어느 곳에서든 참조 된다.
지역 스코프 (Local scope) : 정의된 함수 내에서만 참조되는 것을 의미하며, 밖에서는 참조 되지 않는다.
렉시컬 스코프
함수를 어디 선언하는지에 따라 상위 스코프가 결정되는 자바스크립트를 포함한 대부분의 프로그래밍 언어는 렉시컬 스코프를 따름
var x = 1;
function foo() {
var x = 10;
bar();
}
function bar() {
console.log(x);
}
foo(); // 1
bar(); // 1
위와 같은 상황에서 bar 함수에서 참조하는 x 변수는 bar 함수의 상위 스코프가 무엇인지에 따라 결정된다. 따라서, 상위 스코프가 무엇인지 알려면 bar 함수가 어디에 선언되었는지 봐야되는데, 위 코드에서는 bar 함수가 전역에 선언되었으므로 상위 스코프는 전역 스코프가 된다. 그래서 bar 함수 내의 x 변수는 전역에 선언된 x 변수를 참조하게 된다.
클로저
반환된 내부함수가 자신의 렉시컬스코프를 기억하여 자신의 스코프 밖에서 호출되어도 그 환경에 접근할 수 있는 것
const outerFunc = () => {
let x = 10; // '자유 변수' 라고 한다.
// 클로저
const innerFunc = (y) => {
x = x + y;
console.log(x);
}
return innerFunc;
}
const addFunc = outerFunc();
addFunc(5); // 15
addFunc(10); // 25
위 코드에서 innerFunc의 x는 렉시컬 스코프에 의해 outerFunc의 지역변수 x를 참조하고 있다.
그리고 outerFunc는 const addFunc = outerFunc(); 구문에서 호출된 후 콜스택에서 제거된다.
따라서, 이후에 addFunc를 호출 할 때 innerFunc의 x를 참조할 수 없어 보이는데, 외부함수 실행 컨텍스트 내의 *활성 객체가 내부함수에 의해 참조되는 한 유효하기 때문에 그렇지 않다.
즉, 내부함수가 유효한 상태에서 외부함수가 종료되어도, 외부함수의 x 변수를 참조할 수 있다. 여기서 내부함수를 클로저라고 한다.
클로저가 필요한 이유
1. 전역변수를 줄일 수 있다.
전역변수는 예상치 못한 Side Effect를 일으킬 수 있기에 최대한 줄이는 것이 좋다.문에 최대한 전역변수를 줄여서 코딩해야한다.
하지만 프로그램 구현 시 함수 하나에 사용하는 전역변수가 필요한 순간이 있다. 이럴 때 클로저가 유용하게 사용된다.
2. 비슷한 형태의 코드를 재사용률을 높일 수 있다.
인자에 open,close,content를 한번에 다 받는다면,This is my content! 와 같은 값을 출력을 하고 싶을 때 가독성이 떨어질 수 있다.
하지만 클로져로 구현하면 코드의 가독성도 좋은 재사용하기 편한 코드를 구현할 수 있음.