Closure
자바스크립트에서 closure는 함수의 scope에 존재하지 않는 변수에 접근이 가능한 함수를 의미한다. 대표적인 클로저는 다음과 같다.
func라는 함수 내부에는 str이라는 변수와 funcClosure이라는 함수가 존재한다. funcClosure는 함수 scope에 존재하지 않는 str이라는 변수를 출력하는 함수이다. 이때 lexical scoping에 의해 funcClousre 함수는 'Hi'라는 문자열 출력하도록 선언할 때 결정된다. 이때 funcClousre 함수는 함수이면서 함수 scope에 존재하지 않는 변수에 접근이 가능하므로 closure가 된다.
Closure을 이해하기 위해서는 scope와 lexcial scoping을 완전히 이해하고 있어야한다.
https://jongbeom-dev.tistory.com/116?category=863255
Closure가 특이한 이유는 closure이라는 변수에 func 함수의 리턴값인 funcClosure를 저장하는데 이때 funcClosure scope 밖인 str이라는 변수와 변수에 Hi라는 문자열이 저장되어 있다는 사실을 기억하기 때문이다. 만약 이를 기억하지 못했다면 closure함수를 실행했을 때 Hi라는 문자열이 출력되지 않을 것이다.
클로저의 정의를 검색하면 함수와 함수가 선언된 어휘적 환경의 조합이라고 한다. 이때 말하는 어휘적 환경이란 위의 예제와 같이 lexcial scoping에 의해 함수 scope가 아닌 변수에 접근 할 수 있도록 선언할 때 결정하는 상황을 의미한다.
Closure를 사용하는 대표적인 예시
Closure를 이야기할 때 빼놓을 수 없는 예제가 있다. 반복문 내에서 setTimeout을 사용하는 함수 예제이다.
이 코드를 lexical scoping의 이해 없이 본다면 1초 간격으로 0, 1, 2를 차례로 출력하길 예상할 것이다. 하지만 결과를 보면 1초 간격으로 3을 출력하게된다. setTimeout 함수 scope에는 변수 i가 존재하지 않으며 lexcial scoping에의해 func 함수 내에 존재하는 변수 i를 출력하게 된다. 이때 for문이 끝나면 func 내의 i 변수는 3가 되고 setTimeout 함수에서 사용하는 i는 func 내의 변수 i이기 때문에 3을 출력하게 된다. 이를 해결하기 위해서는 for 문안에 변수 i에 대입된 값을 받아 setTimeout을 실행하는 함수를 정의하고 호출해야한다.
이 경우는 원래의 의도대로 1초 간격으로 0, 1, 2를 차례로 출력한다. func 안에서 func2를 호출하고 func2안에 i값을 인자로 전달하였다. 이때 setTimeout 함수의 인자로 전달되는 익명함수가 closure가 된다. 함수이면서도 변수 j가 함수 scope에 없으며 lexical scoping에 의해 func2 함수의 인자로 전달되는 j값을 사용하도록 선언할때 결정된다. 따라서 인자로 전달되는 j값인 0, 1, 2를 출력하게 된다.
참고자료
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
https://hyunseob.github.io/2016/08/30/javascript-closure/
'개발 공부 > JavaScript 공부' 카테고리의 다른 글
[JavaScript] 프로미스(Promise) (0) | 2020.03.29 |
---|---|
[JavaScript] 호출 스택(Call Stack)과 이벤트 루프(Event Loop) (0) | 2020.02.25 |
[JavaScript] Spread syntax (전개 구문) (0) | 2020.02.17 |
[JavaScript] 스코프 - scope, lexical scoping, hoisting (0) | 2020.02.16 |
[JavaScript] Console 객체 (2) (0) | 2020.02.16 |