교수님이 열심히 클로저 함수 강의해주시던 건 기억이 나지만 (시험 문제에도 나왔던 거 같다) 무슨 내용인지는 가물가물하다..
오늘은 클로저 함수에 대해 알아보겠다!
클로저(Closure)란?
MDN에 따르면
클로저는 함수와 함수가 선언된 어휘적 환경(lexical environment)의 조합이다. 즉, 클로저를 사용하면 내부 함수에서 외부 함수의 스코프에 접근할 수 있다. 클로저를 이해하려면 자바스크립트가 어떻게 변수의 유효 범위를 지정하는지(Lexical scoping)를 먼저 이해해야 한다.
Lexical scoping에 대해서 먼저 알아보자
자바스크립트는 Lexical Scope를 따른다! (반대되는 것은 Dynamic Scope)
Lexical Scope는 함수와 변수의 scope를 정의된 위치를 기준으로 상위 scope를 정한다.
Dynamic Scope는 함수와 변수의 scope를 호출된 시점을 기준으로 상위 scope를 정한다.
예를 들어,
var x = 1;
function print1() {
console.log(x);
}
function print2() {
var x = 100;
print1();
}
print2();
Dynamic Scope라면 실행 중 변경되어 100이 출력되고 Lexical Scope라면 1이 출력된다.
다음 예시를 보자.
function init() {
var name='홍길동'; // 지역 변수
function displayName(){ // 내부 함수, closure
alert(name); // 부모 함수에 선언된 변수 사용
}
displayName();
}
init(); // 홍길동
displayName()은 init() 안에 정의된 내부 함수이고 init() 안에서 사용이 가능하다. displayName()의 상위 scope는 Lexical Scope에 따라 init()이 된다. 따라서 init()의 name에 접근할 수 있다.
즉, 중첩 함수는 외부(상위) scope에 선언된 변수에 접근할 수 있다.
그래서 closure는 무엇인가?
다시 MDN을 읽어보면,
클로저는 함수와 함수가 선언된 어휘적 환경(lexical environment)의 조합이다.
이 뜻은 중첩 함수(함수와 함수)에서 lexical scope에 따라 내부 함수에서 외부 함수의 scope에 접근할 수 있다는 말이다.
아주 쉽게!! closure는 내부 함수(closure)에서 외부 함수의 변수를 사용하는 기법이다.
closure는 어디에 쓰일까?
- 정보 은닉
function addNumber() {
var num=0; // 정보은닉
return function () {
return num++;
};
}
var counter=addNumer();
console.log(counter()); // 0
console.log(counter()); // 1
console.log(counter()); // 2
counter에서 변수는 밖으로 노출되지 않으므로 정보은닉이 된다.
- 커링(currying)
커링은 여러 인자를 가진 함수가 있을 때, 각각 인자를 따로 받는 함수를 만들어 호출하는 것으로 재사용에 유리하다.
function greeting(text, name){
console.log(text + ',' + name);
}
이 함수는 text와 name을 둘 다 인자로 받아야 실행된다.
커링을 이용하면 아래와 같이 만들어 볼 수 있다.
function greeting(text){
return function(name){
console.log(text + ',' + name);
}
}
var hello = greeting('hello');
hello('world'); // hello,world
hello('dog'); // hello,dog
+ closure 사용 시 내부 함수가 언제 외부 함수의 변수를 참조하는지 알 수 없기 때문에 외부 함수가 종료되어도 메모리상에 남아있다고 한다. 과다하게 사용 시 메모리 누수가 발생하니 주의!
'IT > JavaScript' 카테고리의 다른 글
자바스크립트에서 뒤로가기 감지하기 (0) | 2022.06.07 |
---|---|
slice와 splice의 차이점 (0) | 2022.04.05 |
padEnd() (0) | 2022.03.30 |
정규식 표현식 (0) | 2022.03.30 |
index값들로 배열에서 삭제하기 (0) | 2022.03.18 |