[Javascript] 11. グローバル変数の問題


これは私が理解した整理内容で、正確ではないかもしれません.😉

グローバル変数の問題


グローバル変数の盲目的な使用は危険です.

11.1変数のライフサイクル


11.1-1ゾーン変数のライフサイクル


変数にはライフサイクルがあります.宣言によって生成され、割り当てによって値が取得され、ある日消えます.
グローバル変数のライフサイクルはアプリケーションのライフサイクルと同じですが、ゾーン変数は関数で宣言され、関数呼び出し時に生成され、関数終了時に消失します.
function foo() {
  var x = 'local';
  console.log(x); // local
  return x;
}

foo();
console.log(x); //ReferenceError
例のxは領域変数であり、foo関数が呼び出されるまで生成されない.
前に変数ハウスティンを勉強しました.変数宣言は、まず実行時に実行されます.宣言がどこにあるかにかかわらず、この概念はグローバル変数にのみ適用されます.
では、地域変数はいつ発表されますか?
ゾーン変数を含む関数が呼び出された場合、ゾーン変数はまずJavaScriptエンジンによって変数宣言され、関数体のコードが1つずつ実行され、割り当てられます.また、関数が終了すると変数も消え、ライフサイクルが終了します.
すなわち,領域変数のライフサイクルは関数のライフサイクルと一致する.
関数内部で宣言された領域変数は、関数生成のscopeに登録されます.
スキャンは一般的に関数終了時には関数生成のスキャンも消失するが,スキャンを参照している人がいればスキャンは解除されず生存する.
var x = 'global';

function foo() {
  console.log(x); // (A)
  var x = 'local';
}

foo();
console.log(x); // global
上記のコード(A)が返す結果を推定してみましょう.
前の領域変数の宣言は関数が呼び出され、体が実行される前に宣言されます.
したがって(A)文は、foo関数を呼び出した後に実行され、(A)文は、xに割り当てられる前にlocalに戻る領域変数undefinedを参照する.
なぜ未定義を返すのですか?🤔
変数宣言は、JavaScriptエンジンによって実行前に宣言されますが、実行後に関数体の文が順次実行され、割り当てられるためです.
ホイスティンはスコフ単位で動作する.
グローバル変数の役割は、グローバル変数の宣言がグローバルscopeの前に昇格するように、グローバルで有効であり、ゾーン変数の役割はゾーンscopeの前に昇格するようになります.つまり、HOISTINGはJavaScript固有の特徴であり、変数宣言がscopeのフロントエンドに昇格したように動作する.

11.1-2グローバル変数のライフサイクル


関数とは異なり、グローバルコードは明示的な呼び出しなしで実行され、戻り文は使用できません.したがって、最後の文が実行され、実行可能な文がなくなると、終了します.
グローバル変数はグローバルオブジェクトのプロパティとなり、ライフサイクルもグローバルオブジェクトと一致します.
グローバルオブジェクトとは?🤔
グローバルオブジェクトは、コードが実行される前にJavaScriptエンジンによって任意のオブジェクトより先に作成された特殊なオブジェクトです.オブジェクト(オブジェクト、String、Number、Function、Array...)環境に関連するホストオブジェクト(クライアントWeb APIまたはNode.jsのホストAPI)、およびvarキーワードとして宣言されたグローバル変数およびグローバル関数をpropertyとして使用します.
ブラウザ環境では、グローバルオブジェクトはwindowであるため、varキーワードとして宣言されたグローバル変数は、グローバルオブジェクトwindowのpropertyである.したがって、ブラウザ環境でvarキーワードとして宣言されたグローバル変数は、Webページを閉じる前に有効である.
すなわち、varキーワードで宣言されるグローバル変数のライフサイクルは、グローバルオブジェクトのライフサイクルと一致する.

11.2グローバル変数の問題


  • 無名の欠陥
    グローバル変数を宣言する目的は、任意の場所で参照および割り当て可能な変数を使用することです.
    これにより、すべてのコードがグローバル変数を参照し、変更する暗黙的な組み合わせが可能になります.
    これらのため、思わぬ状態変化が起こり、可読性も低下する可能性がある.

  • ロングライフサイクル
    グローバル変数のライフサイクルが長い.そのため、メモリとステータスの変更時間が長くなり、機会も多くなります.
    さらに、varキーワードを使用すると、変数の宣言を繰り返すことができます.したがって、ライフサイクルの長いグローバル変数は変数名を繰り返す可能性があります.

  • スキャンチェーンの終点に存在する
    グローバル変数がスキャンチェーン上の終点に転載されます.これは、変数を検索すると、グローバル変数が最後に検索されることを意味します.
    すなわち,グローバル変数の探索速度が最も遅い.

  • ネーミングスペース汚染
    JavaScriptの最大の問題の1つは、ファイルが別々であってもグローバルスキャンを共有することです.
    したがって、別のファイルで同じ名前のグローバル変数またはグローバル関数が同じscopeに存在する場合、予想外の結果が得られます.
    いつネーミングスペース汚染が発生しますか?🤔
  • 複数のライブラリファイルを取得する場合は
  • を使用する.
  • 大型プログラムの作成時は
  • である.
  • 複数人がプログラムを作成するとき、
  • 11.3グローバル変数を無効にする方法


    グローバル変数を使用する必要がある理由が見つからない場合は、領域変数を使用する必要があります.変数のスキャンが狭いほど良いです.
    グローバル変数の使用を抑制する方法を見てみましょう.

    11.3-1即時実行関数


    すべてのコードが即時実行関数に囲まれている場合、すべての変数は即時実行関数の領域変数になります.
    (function () {
      var foo = 10; // 즉시 실행 함수의 지역 변수
      // ...
    }());
      
    console.log(foo);
    このメソッドはグローバル変数を生成しないため、ライブラリなどでよく使用されます.

    11.3-2名前空間オブジェクト


    方法は、グローバルにネーミングスペースの役割を果たすオブジェクトを作成し、グローバル変数として使用したい変数をpropertyに追加することです.
    var MYAPP = {}; // 전역 네임스페이스 객체
    
    MYAPP.name = 'Lee';
    
    console.log(MYAPP.name); // Lee
    また、別のネーミングスペースオブジェクトをネーミングスペースオブジェクトに追加して、ネーミングスペースを階層的に整理することもできます.
    var MYAPP = {}; // 전역 네임스페이스 객체
    
    MYAPP.person = { // 전역 네임스페이스 객체에 person이라는 새로운 객체를 생성
      name: 'Lee',
      address: 'Seoul'
    };
    
    console.log(MYAPP.person.name); // Lee
    ネーミングスペースを分離すると識別子の競合を防止できますが、オブジェクト自体がグローバル変数に割り当てられているため、想像したほど役に立たないように見えます.

    11.3-3モジュールモード


    モジュールモードはクラスを模倣し,関連する変数と関数を集合させ,直ちに実行関数でモジュールを囲む.
    モジュールモードはJavaScriptの強力な機能モジュールに基づいており、グローバル変数の抑制とパッケージングを実現できます.
    カプセル化とは?🤔
    オブジェクトの状態を表すPropertyとPropertyを参照し、操作可能な動作方法を組み合わせて、オブジェクトの特定のPropertyまたはメソッドを非表示にします.情報非表示と呼ばれます.
    ほとんどのオブジェクト向けプログラミング言語では、public, private, protectedなどのアクセス制限を使用してクラスを構成するメンバーの公開範囲を制限できますが、JavaScriptではこれらのアクセス制限は提供されません.したがって、モジュールモードは、情報非表示を実現するために使用される.
    var Counter = (function() {
      // private 변수
      // 모듈 패턴은 클래스를 모방해서 관련이 있는 변수와 함수를 모아 즉시 실행 함수로 감싸 하나의 모듈을 만든다.
      // 식별자 Counter는 모듈인가? 모듈이다.
      // 공개하지 않을 변수나, 함수는 프로퍼티로 추가하지 않고 공개할 함수나 변수는 모듈의 프로퍼티로 추가한다.
      var num = 0;
      
      return {
        increase() {
          return ++num;
        },
        decrease() {
          return --num;
        }
      };
    }());
    
    // private 변수는 외부로 노출되지 않는다.
    console.log(Counter.num); // undefined
    
    console.log(Counter.increase()); // 1
    console.log(Counter.decrease()); // 0
    上記の例のインスタント関数は、オブジェクトを返します.このオブジェクトには、外部に露出したい変数または関数が含まれ、返されます.
    難解😭
    後で、「シャーシ」の概念を振り返ってから戻りましょう.

    11.4-3 ES 6モジュール


    ES 6モジュールは、ファイル自体の独立したモジュールスキャンを提供する.
    したがって、モジュール内でvarキーワードとして宣言される変数は、グローバル変数でもwindowオブジェクトのpropertyでもない.
    使用時、scriptラベルにtype='module'のツリー図を追加し、ロードしたJavaScriptファイルをモジュールとして操作します.モジュールのファイル拡張子はmjsが推奨されます.
    <script type='module' src = 'lib.mjs'></script>
    これまでES 6モジュールと比較してWebpackなどのモジュールバンドルパッケージが一般的に使用されてきた.
    🤔 Webpackって何?
    👤 後で調べましょう.
    の最後の部分