티스토리 뷰

클로저(closure)는 내부함수가 외부함수의 맥락(context)에 접근할 수 있는 것을 가르킨다.

클로저는 자바스크립트를 이용한 고난이도의 테크닉을 구사하는데 필수적인 개념으로 활용된다. 

 

 function outter() {
        //내부에 inner이라는 지역변수를 만들고 그 변수에 함수를 할당한 것으로 이해하면 쉽습니다.
        function inner() {
          const title = "coding everyBody";
          alert(title);
        }
        inner();
      }
      outter();
  • outter()함수는 외부함수이고 inner()함수는 내부함수이다. 
 function outter() {
 //title은 outter의 지역변수이다.
        const title = "coding everyBody";
        function inner() {
          alert(title);
        }
        inner();
      }
      outter();
  • title 은 outter의 지역변수이다.
  • inner()함수는 외부함수 outter()의 지역변수 title에 접근가능하다. ->내부함수가 외부함수의 지역변수에 접근가능하다. 이것을 바로 클로저라고합니다. 

 

 

클로저는 내부함수와 밀접한 관계를 가지고 있는 주제이다. 

  • 위의 코드는 return 값으로 내부함수를 반환하고 있다. 우리는 그것을 inner라는 변수에 담아서 inner()함수를 실행하고 있다. 여기서 의문이 드는 것은 return의 의미는 바로 작업을 종료, 즉 outter()함수가 소멸했다는 뜻인데 어떻게 inner()함수가 외부함수인 outter의 지역변수 title에 접근할 수 있냐는 것이다. 
  • 이처럼 내부함수는 외부함수의 지역변수에 접근할 수 있는데 외부함수는 외부함수의 지역변수를 사용하는 내부함수가 소멸될 때까지 소멸되지 않는 특성을 클로저라고 한다.  

Private Variable

Private 속성은 객체의 외부에서는 접근 할 수 없는 외부에 감춰진 속성이나 메소드를 의미한다. 이를 통해서 객체의 내부에서만 사용해야 하는 값이 노출됨으로서 생길 수 있는 오류를 줄일 수 있다.

 

TIP: 함수의 매개변수는 함수 안에서 지역변수로 사용됩니다.

function factory_movie(title) {
//매개변수 title은 함수factory_movie()의 지역변수입니다. 
        return {
          // 객체를 리턴
          //get_title(), set_title()메소드를 가지고있음
          get_title: function () {
            return title;
          },
          set_title: function (_title) {
            if (typeof _title === "string") {
              title = _title;
            } else {
              alert("타이틀은 문자로 작성해야합니다. ");
            }
          },
        };
      }
      ghost = factory_movie("Ghost in the shell");
      matrix = factory_movie("Matrix");
      alert(ghost.get_title()); //Ghost in the shell
      alert(matrix.get_title()); //Matrix
      ghost.set_title(1); //타이틀은 문자로 작성해야합니다.
      ghost.set_title("공각기동대");
      alert(ghost.get_title()); //공각기동대
      alert(matrix.get_title()); //Matrix
  • 위의 코드를 보면 객체를 리턴하고 있는 외부함수 factory_movie가 매개변수로 title을 받고 있다. 여기서 title은 외부함수의 지역변수로 사용된다. 리턴하고 있는 것이 객체이지만 객체에 메소드가 정의돼있기 때문에 내부함수로 생각하면 됩니다. 이 내부함수 get_title()은 반환값으로 외부함수의 title(factory_movie의 지역변수 title)을 사용하고 있습니다. set_title()메소드의 경우 매개변수로 _title을 받아서 그 값을 title에 담아 변경하고 있습니다. 이는 곧 _title 값을 외부함수의 지역변수 title에 담는다는 것입니다. 
  • 동일한 외부함수 안에서 만들어진 내부함수나 메소드는 외부함수의 지역변수를 공유한다. 
  • 같은 외부함수를 공유하고 있는 ghost와 matrix(객체를 담은 변수)의 get_title의 결과는 서로 다릅니다. -> 외부함수가 실행될 때마다 새로운 지역변수를 포함하는 클로저가 생성되기 때문에 ghost와 matrix는 서로 완전히 독립된 객체가 됩니다.
  • 외부함수의 지역변수 title은 내부에 정의된 객체의 메소드에서만 접근 가능할 수 있는 값이다. 이 말은 title의 값을 읽고 수정 할 수 있는 것은 factory_movie 메소드를 통해서 만들어진 객체 뿐이라는 의미다. ->클로저의 이러한 특성을 이용하여 Private한 속성을 사용할 수 있다.(원래는 JS에서 Private한 속성을 지원하지 않습니다.)

※이슈: 예제에서는 if문의 조건식을 "String"으로 대문자로 사용하셨지만 실제로 typeof _title을 해보면 string으로 나옵니다. 그냥 typeof _title === "String"을 하면 계속해서 else문이 실행되니 주의, String -> string (o)

 

🤢클로저의 활용

 //변수선언을 var로 하게되면 오류가 나는 코드이지만 
    //const 와 let을 쓰면 원하는 결과가 나온다. 
    //원하는 결과: 0,1,2,3,4
    //var 을 사용한 코드의 결과: 5가 5번 출력
    // var const let 그리고 그냥 변수명만 있을 때의 특성을 알아두자
      var arr = [];
      for (var i = 0; i < 5; i++) {
        arr[i] = function () {
          return i;
        };
      }
      for (var index in arr) {
        console.log(arr[index]());
      }
  • 이 코드에 대해서는 제대로 이해하지 못했으므로 다시 보고 정리하도록 함
댓글