자바스크립트 클로저 함수 예제 – 변수 스코프란

자바스크립트 클로저 함수 (Closure) 즉, 내부함수, 외부함수와 의 관계로 인해 발생하는 자바스크립트의 개념입니다.

클로저(Closure)란, 내부 함수의 경우, 외부함수의 지역 변수에 접근이 가능한데, 외부 함수의 실행이 끝난 이후 외부함수가 소멸된 이후에도 내부 함수가 외부 함수의 변수에 접근 할 수 있는 매커니즘을 이야기 합니다.

자바스크립트 클로저 함수 예제 변수 스코프란

자바스크립트 변수 스코프 – Lexical 환경

아래의 코드는 outter 안에 함수에서 name이라는 지역 변수를 사용하는 예제입니다.

<body>
    <script>
      function outter() {
        let name = "SAPUI5 자바스크립트";
        return function () {
          console.log(name);
        };
      }
 
      inner = outter();
      inner(); //  "SAPUI5 자바스크립트" 출력됨
    </script>
  </body>
 

outter()이 끝난 이후에도 outter()내의 지역변수는 살아있음을 알 수 있습니다.

즉, 외부 inner 변수를 실행한 시점에서는 name 지역 변수가 살아있고, 이는 외부함수의 경우 외부함수의 지역변수를 사용하는 내부함수가 소멸되기 전까지는 소멸 되지 않음을 의미합니다.

 

자바스크립트 스코프 체인

아래의 예제는 outer() 스코프에 name 변수가 있지만 inner() 에도 name이 있기 때문에 출력은 영희가 찍히게 됩니다.

inner() 함수에서는 먼저 본인의 스코프 상의 name이라는 변수를 찾기 때문에 inner() 안에 있는 name을 인식하고 출력합니다.

<body>
    <script>
      function outer() {
        var name = "철수";
 
        function inner() {
          var name = "영희";
          console.log(name);
        }
        inner();
      }
      outer();
    </script>
  </body>

아래의 예제에서, age 변수는 스코프 체인에 의해 inner() 에서도 참조하여 사용할 수 있습니다.

<body>
    <script>
      function outer() {
        var name = "철수";
        var age  = 30;
 
        function inner() {
          var name = "영희";
          console.log(name);
          console.log(age);
        }
        inner();
      }
      outer();
    </script>
  </body>

스코프 체인에 의해, inner()에서 age라는 변수를 본인의 스코프에서 먼저 찾습니다. 하지만, inner()에는 없어 스코프를 확장하여 본인을 호출한 outer()에서 해당 변수를 찾습니다. outer()에서 발견이 되므로 해당 변수를 찍게 됩니다.

본인을 호출한 outer()에서 해당 변수를 찾아 출력

변수를 찾아가는 순서는 아래와 같습니다.

내부 Lexical 환경 → 외부 Lexical 환경 → 전역 Lexical 환경

 

자바스크립트 클로저의 개념

outer()의 리턴값으로 내부의 inner 함수를 전달하게 되는데, 이 리턴값을 변수를 통해 할당 받아 실행하게 되면 내부함수의 지역변수는 계속 살아있게 됩니다.

<body>
    <script>
      function outer() {
        var name = "철수";
        var age = 30;
 
        function inner() {
          var name = "영희";
          console.log(name, age);
        }
        return inner;
      }
 
// 리턴되는 함수를 변수로 받는 경우에는 내부함수의 지역변수는 유지됨
      var retFunc = outer();
      retFunc();
    </script>
</body>

다음과 같이 function 안에서 내부 function 을 만들게 되고 내부 함수 내에서 상위 스코프에 변수를 사용하게 되는 함수를 클로저 함수라고 합니다.

<body>
    <script>
      function makeSum(x) {
        return function (y) {
          return x + y;
        };
      }
 
      // makeSum에 5가 들어감
      const sum3 = makeSum(5);
      // makeSum을 sum3 변수를 통해 받았기  때문에 x = 5가 살아있음
      //따라서 x + y = 5+ 10 = 15가 출력되게 됨.

      console.log(sum3(10));
      console.log(sum3(3));
      console.log(sum3(20));
 
    </script>
  </body>

makeSum의 내부 변수 x = 2로 기억되고, 각각의 호출 결과로 15, 8, 25가 출력되게 됩니다.

따라서 아래와 같이 내부 변수 x 값을 변경해주는 경우 해당 값이 지속적으로 살아서 업데이트 되고 있음을 확인할 수 있습니다.

<body>
    <script>
      function outer() {
        let x = 2;
 
        const inner = (y) => {
          // outer의 내부변수 x를 업데이트함
          return (x = x + y);
        };
 
        return inner;
      }
 
      const makeSum = outer();
      console.log(makeSum(2)); // 4 출력
      console.log(makeSum(3)); // 7 출력
      console.log(makeSum(4)); // 11 출력
    </script>
  </body>

변수로 할당 받은 클로저 함수 내의 지역변수는 사라지지 않고 계속 유지됨

이상으로 자바스크립트 클로저에 대해서 알아보았습니다. 어휘적 범위 등의 좀 더 자세한 사항은 모질라 MDN 문서 클로저 – Javascript 를 확인해 보시기 바랍니다.

자바스크립트 클로저 함수 이해를 위한 자바스크립트 함수에 기초가 필요하신 분은 자바스크립트 함수(function) 이해 글을 참고해보시기 바랍니다.