[JS]ScopeとCloserについて


ScopeとCloserについて


Javascriptを深く理解するには、Closerを理解し、Scopeを理解するにはScopeを理解する必要があります.
有効範囲(scope)はJavaScriptだけでなく、すべてのプログラミング言語の中で最も基本的な概念の一つです.しかし、JavaScriptの有効範囲は他の言語の有効範囲とは異なる.

1.有効範囲(Scope)


プログラミング言語では、有効範囲とはどの範囲を参照するかを指します.
  • グローバルスコープ(Global Scope):スクリプト全体で参照され、任意の場所で参照されます.
  • 領域範囲(Local scope):定義された関数内でのみ参照され、外部では参照されないことを示します.
  • 有効範囲の特徴は次のとおりです.
  • 関数単位の有効範囲(関数-レベル-範囲)
  • 変数名
  • の繰り返しを許可
  • 世界宣言
  • 黙示
  • Lexical scoping (Static scoping)
  • 1-1. function-level scope


    function-level scopeとは、関数コードブロック内で宣言された変数が関数コードブロック内でのみ有効であり、関数外部では無効であることを意味します.
    var x = 0;
    {
      var x = 1;
      console.log(x); // 1
    }
      console.log(x); // 1
    
    let y = 0;
    {
      let y = 1;
      console.log(y); // 1
    }
      console.log(y); // 0

    1-2. 重複変数名の許可


    クローン領域に変数を宣言すると、その変数はグローバルな役割ドメインを持つグローバル変数となり、任意の場所で参照できます.
    var global = 'global';
    
    function foo() {
      var local = 'local';
      console.log(global); // global
      console.log(local); // local
    }
    foo();
    
    console.log(global); // global
    console.log(local); // Uncaught ReferenceError: local is not defined

    1-3. 大域を黙示する(大域を隠す)


    変数の前に`varを付けると、無名のグローバル変数になります.
    function foo() {
      x = 1;   // Throws a ReferenceError in "use strict" mode
      var y = 2;
    }
    
    foo();
    
    console.log(x); // 1
    console.log(y); // ReferenceError: y is not defined

    1-4. Lexical scoping (Static scoping)


    」JavaScriptには、関数宣言時の有効範囲があります.
  • 例1
  • var number = 1234
    
    function printNumber() {
      console.log(number);
    }
    
    function wrapper() {
      number = 4321
      printNumber();
    }
    wrapper(); // 4321
    printNumber関数を実行する前にnumberの値を変更したため、wrapper関数を実行すると値が変化します.
  • 例2
  • var number = 1234
    function printNumber() {
      console.log(number);
    }
    
    function wrapper() {
      var number = 4321
      printNumber();
    }
    wrapper(); //1234
    パッケージ関数でvarキーワードを使用すると、結果が異なります.
    関数を最初に宣言した瞬間、関数内部の変数は、ミラーに最も近い(より高い範囲)変数を参照し続けます.
    上記の例では、printNumber関数のnumber変数は、宣言時に最も近いグローバル変数numberを参照する.

    2.スキャンチェーン(Scope Chain)


    新しく定義したスキャナーは、親のスキャナーに近づくことができます.
    scopeチェーンはscopeの最も内部でscopeチェーンに沿って外に検索されます.

    3.キャビネット(閉)


    レコーダは、宣言環境(レイクシー)での関数のスキャンを記憶し、スキャン外で実行してもスキャンにアクセスできるようにする技術です.
    // changeCount는 inner함수
    // 객체를 리턴하고 있고 객체 안에는 increase, decrease, show와 같은 inner함수들을 저장
    
    const counter = function() {
      let count = 0;
      function changeCount(number) {
        count += number;
      }
      return {
        increase: function() {
          changeCount(1);
        },
        decrease: function() {
          changeCount(-1);
        },
        show: function() {
          alert(count);
        }
      }
    };
    
    // counter를 실행하면 outer함수 스코프를 기억하고 있는 클로저들이 담긴 객체를 반환
    // counterClosure는 counter함수 내부에 정의된 count나 changeCount에 접근 가능
    
    const counterClosure = counter(); 
    counterClosure.increase(); // 
    counterClosure.show(); // 1
    counterClosure.decrease();
    counterClosure.show(); // 0
  • は内部関数であり、外部関数の領域変数にアクセスすることができ、外部関数の実行が完了しても、外部関数が破棄された後も、内部関数は外部関数の変数にアクセスすることができる.このメカニズムをCloserと呼ぶ.
  • 4.どこでCloserフックを使いますか?


    1.React HookのusState


    関数型構成部品の前の状態と現在の状態が変化しているかどうかを検出するには、関数の実行時に前の状態の情報を持つ必要があります.Reactはこのプロセスでモジュールを使用します.

    2.ユーザ状態の動作原理



    userStateは、initialstateをパラメータとして受け入れる関数として宣言されます.関数では、別の関数resolveDispatcherによって返されたdispatcherにinitialstateが渡されるuserStateメソッドの結果を返します.

    resolveDispatcher関数を使用して、ReactCurrentDispatcherの現在の値を返します.
    さらにReactCurrentDispatcher

    グローバル宣言のcurrent値を含む変数.
    useStateは、外部から宣言されたステータス値にアクセスして古いステータスを取得し、変更されたステータス値を管理します.関数型構成部品は、最終的には関数であるため、モジュールによって宣言された時点でアクセスできる外部ステータス値にアクセスし続けることができます.関数型構成部品でステータス値を変更すると、外部値が変更され、再レンダリング(=関数の再呼び出し)によって新しい値が得られます.

    5.整理


    モジュールは、内部関数が外部関数にアクセスできる領域変数であり、外部関数が実行され、外部関数が消えた後も、内部関数は外部関数の変数にアクセスできます.
    (モジュールは、関数が宣言された環境(ディレクトリ)を記憶します.これにより、関数がミラーの外で実行されると、ミラーにアクセスできます.)
    Reactで関数型構成部品のステータスを管理するには、構成部品の外部に格納された値を使用し、エンクロージャからアクセスしてステータスを比較および変更します.useStateは、エレメント内部で値を変更するのではなく、エレメント外部で値を変更するので、ステータスが変更されると、エレメントの値は以前の値に従います.
    各構成部品のステータス情報は配列形式で格納されるため、条件文または繰返し文でステータスを変更するhookを使用すると、誤った順序の値が参照される可能性があります.

    リファレンス

  • https://velog.io/@bathingape/%EC%8A%A4%EC%BD%94%ED%94%84Scope%EC%99%80-%ED%81%B4%EB%A1%9C%EC%A0%80Closure-%EC%9D%B4%ED%95%B4
  • https://velog.io/@ggong/useState-Hook%EA%B3%BC-%ED%81%B4%EB%A1%9C%EC%A0%80