본문 바로가기

기술면접 준비

클로저를 사용하면 외부의 함수에 접근할 수 있다고?

📕 오늘의 질문

클로저란?

외부 함수에 접근할 수 있는 내부 함수를 말합니다. MDN은 클로저를 함수와 함수가 선언된 어휘적 환경의 조합이라고 정의합니다. 하지만 제게 가장 와닿았던 정의는 제가 참조한 블로그에서 봤던 정의였습니다.

 

"자신이 선언될 당시의 환경을 기억하는 함수입니다."

> 클로저란 함수가 자신이 선언될 당시의 환경을 기억하여, 내부함수가 외부함수의 맥락(contex)에 접근할 수 있는 것을 의미합니다.

    function init() {
      var name = "Mozilla"; // name은 init에 의해 생성된 지역 변수이다.
      function displayName() { // displayName() 은 내부 함수이며, 클로저다.
        alert(name); // 부모 함수에서 선언된 변수를 사용한다.
      }
      displayName();
    }
    init();

위 코드를 살펴보면 함수 내에 또다른 함수가 선언되어 있는 것을 볼 수 있습니다. 이때, 클로저가 생성될 때 범위 내에서 지역변수를 자유변수로 만드는 것을 캡쳐라고 합니다.

 

MDN은 클로저를 이해하기 위해선 우선 자바스크립트가 어떻게 변수의 유효범위를 지정하는지를 이해해야 한다고 말합니다. 이 변수의 유효범위를 지정하는 것을 어휘적 범위 지정(Lexical scoping)이라고 합니다. 하지만 그전에 또 알아야 할 것이 있습니다. 그건 바로 스코프입니다.

 

1) 스코프(Scope)란?

자바스크립트에서 스코프란 '범위'를 의미합니다.

 

스코프에는 규칙이 있는데요!

(1) 안쪽 스코프에서 바깥쪽 스코프로는 접근할 수 있지만 반대는 불가능합니다.

(2) 스코프는 중첩이 가능합니다.

(3) 전역 스코프(global)와 지역 스코프(local)

(4) 지역 변수 > 전역 변수

전역 스코프에서 선언한 변수는 전역 변수이고, 지역 스코프에서 선언한 변수는 지역 변수가 됩니다. 이때 지역 변수는 전역 변수보다 더 높은 우선 순위를 가집니다.

 

기억해야 할 것은 함수의 스코프는 함수가 어디서 실행됐느냐가 아니라 어디서 선언되었는지에 달려있다는 점있니다.

 

2) 어휘적 범위 지정이란? (Lexical Scope/Static Scope)

    function init() {
      var name = "Mozilla"; // name은 init에 의해 생성된 지역 변수이다.
      function displayName() { // displayName() 은 내부 함수이며, 클로저다.
        alert(name); // 부모 함수에서 선언된 변수를 사용한다.
      }
      displayName();
    }
    init();

"어휘적(lexical)이란 어휘적 범위 지정 과정에서 변수가 어디에서 사용 가능한지 알기 위해 그 변수가 소스 내 어디에서 선언되었는지 고려한 다는 것을 의미합니다...중첩된 함수는 외부 범위에서 선언한 변수에도 접근할 수 있습니다."

 

다시 클로저로 돌아와서

출처: 생활코딩 'JavaScript - closure' 강의

 

출처: 생활코딩 'JavaScript - closure' 강의

함수를 함수 안에 적용하면 그 함수의 부모 함수의 스코프에 접근할 수 있습니다. 보시다시피 첫 번째 이미지에서는 fn2 함수가 fn1 함수 밖에 선언되어 l2 값을 콘솔로 찍을 때 값이 undefined로 나오지만, 두 번째 이미지에서 fn2 함수가 fn1 함수 내부에서 선언되자 에러 없이 값이 잘 찍히는 것을 볼 수 있습니다. 이때 이 내부 함수, fn2 함수를 클로저라고 부릅니다.

 

 

참고자료

https://developer.mozilla.org/ko/docs/Web/JavaScript/Closures

https://hanamon.kr/javascript-클로저/