ろこう


🎅 ろこう

  • Closureとは、関数(inner function)が自分の属するLexical環境を記憶し、関数がLexical Scopeの外で実行されたときにもそのScopeにアクセスできるようにする機能である.(scope chain)
    すなわち、関数で宣言された変数が関数내부で使用されると、クロックが生成される.

  • プロトタイプベースの言語javascriptは、클로저を介してクラスベースの言語のようにカプセル化およびモジュール化された操作を行うことができる.
  • ►ξ関数を呼び出すのではなく、関数がどこにあるかによって決まる.関数を最初に宣言した瞬間、関数内部の変数は、ミラーに最も近い(より高い範囲)変数を参照し続けます.
    예제 (1)
    
    // 전역 변수 참조
    let name = '전역';
    function log() {      // log함수가 "선언"되는 순간 변수는 스코프를 타고 참조 시작
      console.log(name);  // '전역' 참조
      // 출려값: 지역
    }
    
    function wrapper() {
      name = '지역';       // '지역' 으로 값이 바뀜
      log();              // log함수가 "호출"되는 순간과는 관련X
    }
    wrapper();
    
    
    
    
    
    예제 (2)
    
    let name = '전역';
    function log() {
      console.log(name);   // '전역' 참조 (log함수가 선언되는 시점에 가리키는 변수 참조)
      // 출려값: 전역
    }
    
    function wrapper() {
      let name = '지역';
      log();
    }
    wrapper();
    
    
    
    
    
    예제 (3)
    
    // 외부 변수(name)를 내부(inner)에서 사용
    function outer(){
      let name = 'ladygaga';  // name은 outer에 의해 생성된 지역 변수
      function inner(){
        console.log(name);  // 부모 함수에서 선언된 변수(name) 사용
      }
      return inner;
    }
    
    let innerFunc = outer();  //  inner 함수를 반환(return)받게 된다
    innerFunc();
    // innerFunc()를 호출하면 name에 대한 참조는 메모리에서 소멸하는데, 클로저가 외부변수 name을 통으로 기억함
    // 이러한 이유로 innerFunc는 여전히 자신의 외부에서 생성된 name이라는 변수를 참조할 수 있게 됨.
    
    ❗ 즉, 클로저는 반환된 내부함수가 자신이 선언됐을 때의 환경(Lexical environment)인 
    스코프를 기억하여 자신이 선언됐을 때의 환경(스코프) 밖에서 호출되어도 
    그 환경(스코프)에 접근할 수 있는 함수
    
    ❗ 외부함수(outer)가 이미 반환되었어도 외부함수 내의 변수(name)는 
    이를 필요로 하는 내부함수(inner)가 하나 이상 존재하는 경우 계속 유지된다. 
    이때 내부함수가 외부함수에 있는 변수의 복사본이 아니라 "실제 변수"에 접근한다는 것에 주의!
  • エンクロージャはJS固有の概念ではなく、関数式プログラミング言語(一級関数)が使用する主な特性です!
  • Class概念であり、外部関数に特定の値を非表示にしたり、重複文でvar変数を使用するためにIIFE(インスタント実行関数)を適用する方法などが典型的なClose事例である.
  • // 은닉 사례
    function Counter() {
      // 카운트를 유지하기 위한 자유 변수
      var counter = 0;
    
      // 클로저 (counter를 기억)
      this.increase = function () {
        return ++counter;
      };
    
      // 클로저 (counter를 기억)
      this.decrease = function () {
        return --counter;
      };
    }
    
    const counter = new Counter();
    
    console.log(counter.increase()); // 1
    console.log(counter.decrease()); // 0
    // 이 메소드(increase, decrease)들은 모두 자신이 생성됐을 때의 렉시컬 환경인 
    // 생성자 함수 Counter의 스코프에 속한 변수 counter를 기억하는 클로저이며 렉시컬 환경을 공유한다. 
    
    -----------------------------------------
    
    <script>
        var incleaseBtn = document.getElementById('inclease');
        var count = document.getElementById('count');
    
        var increase = (function () {     // 즉시실행함수
          // 카운트 상태를 유지하기 위한 자유 변수 (전역에 선언하는 것 비추)
          var counter = 0;
          // 클로저를 반환
          return function () {
            return ++counter;
          };
        }());
    
        incleaseBtn.onclick = function () {
          count.innerHTML = increase();
        };
      </script>
     // 스크립트가 실행되면 '즉시실행함수'가 호출되고, 변수 increase에는 "함수"(= function(){return ++counter} )가 할당된다.
     // "이 함수"는 자신이 생성됐을 때의 렉시컬환경을 기억하는 클로저이다.
     // 이때 클로저인 "이 함수"는 자신이 선언됐을 때의 렉시컬 환경인 즉시실행함수의 스코프에 속한 지역변수 counter를 기억한다
    (モジュールは、オブジェクトがオブジェクト向けプログラミングと明らかな共通点を持つ1つ以上のメソッドにデータを関連付けるため、データを操作する関数にデータを関連付けることができます.)

    🎅 クローズドミラーチェーン


    各キャビネットには3つのプローブ(範囲)があります
  • 地域範囲
  • 外部関数範囲
  • グローバル範囲
  • 💡 スコフチェーンとは?
    範囲(scope、変数の有効範囲)間の接続.
    예시 (1)
    
    function outer(){
    	var a = 1;
    	function inner(){ 
    		var b = 2;
    		console.log(a+b);
    	}
    	inner();
    }
    
    outer() // 3
    // a 는 inner 의 스코프에서는 없지만 outer 의 스코프에서 a 의 값을 가져와서 더한다.
    // 내부함수에서 찾을 수 없는 변수이면 상단의 외부함수로간다.
    예시 (2)
    
    var c = 4;
    
    function outer() {
      var a = 1;
      var b = 3;
    
      function inner() {
        var a = 2;
        console.log(a); // 2
        console.log(b); // 3
        console.log(c); // 4
      }
    	
      inner();
    }
    
    outer();
    
    // console.log(a)에서 a의 값을 찾으려고 할 때 들여다보는 곳이 스코프이고 스코프는 함수 단위이다. 
    // 이 때, inner 함수 스코프, outer 함수 스코프, global 스코프가 존재하는데 
    // inner 스코프 안에서 먼저 a가 존재하는지 찾는다.
    
    // 마찬가지로 console.log(b)에서 b의 값을 inner 스코프 안에서 먼저 찾는다. 
    // inner 스코프에는 b가 없기 때문에 그 다음 outer 스코프에 b가 있는지 찾아본다. 
    // inner 함수가 생성된 곳이 outer 함수 범위 안에 있기 때문이다.
    
    // 마찬가지로 console.log(c)에서 c의 값을 inner 스코프 안에서 먼저 찾는다. 
    // inner 스코프에는 c가 없기 때문에 그 다음 outer 스코프에 c가 있는지 찾아본다. 
    // outer 스코프에도 c가 없기 때문에 global 스코프에서 찾는다. 
    // inner 함수가 생성된 곳이 outer 함수 범위 안에 있고, outer 함수가 생성된 곳이 global 범위 안에 있기 때문이다. 
    
    // 이런식으로 스코프끼리 연결된 것이 바로 스코프 체인이다.

    💡 スコフの観点から見ると、Closerとは何ですか?
    決定された関数およびその内部関数が렉시컬 스코핑(Lexical scoping)である場合、決定された関数のスケールはキャビネットとなる.
    var c = 4;
    
    function outer() {
      var a = 1;
      var b = 3;
    
      return function inner() {
        var a = 2;
        console.log(b); // 3
      }
    }
    
    var someFunc = outer();
    someFunc();
    
    // var someFunc = outer(); 에서 outer 함수를 호출해서 실행이 완료되면 outer 함수 내 지역 변수들은 사라질 것 같지만 사라지지 않는다. 
    // 자바스크립트는 함수를 리턴하고 리턴하는 함수가 클로저를 형성하기 때문이다.
    
    // 클로저는 함수와 함수가 선언된 어휘적 환경의 조합이다. 
    // 이 환경은 클로저가 생성된 시점의 유효 범위 내에 있는 모든 지역 변수로 구성된다.
    // someFunc는 outer이 실행될 때 생성된 inner 함수의 인스턴스에 대한 참조다. 
    // inner의 인스턴스는 변수 b가 있는 어휘적 환경에 대한 참조를 유지한다. 
    // 이런 이유로 someFunc가 호출될 때 b는 사용할 수 있는 상태로 남게된다.
    
    // 즉, 원래는 함수 내부에 선언한 변수는 함수가 끝나면 사라지지만, 
    // 클로저가 스코프 체인을 계속 들고 있으므로 outer 함수 내부의 변수를 참조할 수 있게 된다.