Javascript closure(클로저) 정리

이번글은 프론트 면접에서 자주 나오는 클로저에 대해서 정리해보려고 한다.

일단 MDN 사이트에서 클로저에 대한 정의는 아래와 같다.

A closure is the combination of a function and the lexical environment within which that function was declared.
클로저는 함수와 그 함수가 선언됐을 때의 렉시컬 환경과의 조합이다.

여기서 렉시컬 환경이란 함수가 선언됬을때 의 위치 이며 클로저는 자신이 생성된 환경을 기억하는 함수라고 생각하면 된다. 가벼운 예시를 보자

for를 사용하여 setTimeout을 1초뒤에 실행시키는 프로그램을 작성하였다.

하지만 실제 결과는 10이 10번이 나오는 결과를 가져온다. 이유는 var는 함수형 스코프이며 for가 끝난 이후에도 i는 전역에 남아있기 때문이다.

setTimeout이 실행될때 해당 함수는 전역에서 실행한 것으로 간주하며 남아있는 var i를 참조한다. 1초뒤에 i는 10이므로 10이 10회출력되는 문제가 발생한다.

반면 아래의 코드는 function으로 한번 더 감싼 모습이다. 실제 리턴하는 함수는 인라인으로 작성된 function에서 스코핑이 되며 인라인 function이 종료된 이후에도 렉시컬환경에 따라 인라인 function 의 i를 참조할수 있게 된다. 고로 정상적으로 0 ~9 까지 출력이 가능하다.

  • 인라인 function는 종료 이후에도 완전히 사라지지 않고 내부함수에서 참조할 수 있도록 메모리에 남게된다. 잘못된 사용은 성능 문제를 야기시키지만 반대로 잘 사용한다면 각 인스턴스별로 메모리를 차지하는 문제를 줄여 성능을 높여줄 수 있다.

이처럼 본인이 생성된 위치를 기억하는 함수를 클로저라고 하며 이는 자바스크립트가 렉시컬환경으로 구성되있기에 가능한 것이다.

오늘 안 사실이지만 번외로 이런 것도 가능한다(카더라)

전자는 this 를 i로 넘겨준 형태이고 후자는 i를 argument형태로 넘겨준건데,전자는 코드 테스트 시 작성자가 bind특성을 이용하여 처리한거고 금일 테스트 면접관이 알려준건데 i가 argument형태로 넘어가서 독립적인 값으로 된다고 한다.

참고로 bind, call, apply는 this를 별도로 넘겨줘서 외부 함수식으로 처리하는 function의 기능들이고, bind는 새로운 함수 생성을 call apply는 실행하는 역활이다.