[javascript deepdave]14章グローバル変数の問題



14.1変数のライフサイクル


14.1.1ゾーン変数のライフサイクル


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

foo(); //local
console.log(x); //ReferenceError: x is not defined
foo関数を呼び出すまで、領域変数xは作成されません.呼び出さないと、関数内部の変数宣言は実行されないためです.宣言がどこにあるかにかかわらず、変数宣言は最初に実行されます.グローバル変数に限り、実行時までにJavaScriptエンジンが最初に実行します.
上記の例のfoo関数を呼び出すと、関数体の他の文が順次実行される前に、x変数の宣言はまずJavaScriptエンジンによって実行され、x変数は宣言されundefinedに初期化されます.次に、関数体を構成するドアで、「勘定科目」、「勘定科目」、「勘定科目」、「勘定科目」、「勘定科目」、「勘定科目」、「勘定科目」、「勘定科目」、「勘定科目」、「勘定科目」、「勘定科目」、「勘定科目」、「勘定科目」、「勘定科目」、「勘定科目」の順に実行します.ゾーン変数のライフサイクルは、関数のライフサイクルと一致します.
function foo() {
    //변수 x 생성됨 
    var x = 'local'; // 값 할당
    console.log(x);
    return x; 
    //변수 x 소멸
}
関数は生成されたscopeに登録されます.スコフにはレイクシー環境という物理的エンティティがあります.登録したスキャンプログラムが破棄(メモリ解放)されるまで有効です.割り当てられたメモリ領域は、誰も参照しなくなったときにゴミ収集器によって解放され、使用可能なメモリプールに返されます.(メモリ領域を参照している人がいる場合は、まだ保持されています)
var x = 'global';

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

foo();
console.log(x); //global
foo関数内部で宣言された領域変数xは、したがって、出力される値は、グローバル変数xではなく、領域変数xを参照する.すなわち,領域変数は関数の整数で有効である.ただし、変数割当て文を実行する前に、定義されていない値があります.
このように、ホイスティンはスコフ単位で動作します.グローバル変数の反発挙動は、グローバル変数の宣言がグローバル範囲の前に昇格したようにします.したがって、グローバル変数はグローバルに有効です.HOISTINGはJavaScriptの固有の特徴であり、変数宣言のようにScopeのフロントエンドに昇格する.

14.1.2グローバル変数のライフサイクル


グローバルコードは、関数呼び出しのようにグローバルコードを実行する特殊なエントリポイントがなく、コードがロードされるとすぐに解釈され、実行されます.グローバルコードは戻り文を使用できないため、最後の文は実行され、文の実行が不要になったときに終了します.

グローバルオブジェクト


グローバルオブジェクトは、コードが実行される前にJavaScriptエンジンによって任意のオブジェクトより先に生成されるため、オーディオは特殊なオブジェクトです.グローバルオブジェクトはクライアント環境(ブラウザではwindow、サーバ側環境(node.js)ではグローバルオブジェクトです.環境によっては、グローバルオブジェクトを指す異なる識別子(window、self、this、frames、global)が存在するが、ES 11からglobalThisに統一される.
グローバルオブジェクトは、標準的に構築されたオブジェクト(オブジェクト、String、Number、Function、Array...)です.環境に関連するホストオブジェクト(クライアントWeb APIまたはNode.jsのホストAPI)、varキーワードとして宣言されたグローバル変数およびグローバル関数を構成として使用します.
ブラウザ環境では、グローバルオブジェクトはwindowなので、ブラウザ環境でvarキーワードとして宣言されるグローバル変数は、グローバルオブジェクトwindowのpropertyです.グローバルオブジェクトウィンドウは、Webページを閉じる前に有効です.したがって、ブラウザ環境でvarキーワードとして宣言されたグローバル変数は、Webページを閉じる前に有効です.すなわち、varキーワードで宣言されるグローバル変数のライフサイクルは、グローバルオブジェクトのライフサイクルと一致する.
では問題は何ですか??

14.2グローバル変数の問題


無名の結合


グローバル変数を宣言する意図はグローバルです.すなわち、コードで参照および割り当て可能な変数を使用します.これにより、すべてのコードがグローバル変数の暗黙的なマージ(暗黙的結合)を参照して変更できます.変数の有効範囲が大きいほど、コードの可読性が悪くなり、予期せぬ変更のリスクも高くなります.

ロングライフサイクル


グローバル変数のライフサイクルが長い.そのため、メモリリソースも長期的に消費されます.varキーワードは変数の繰り返し宣言を許可するため、ライフサイクルの長いグローバル変数は変数名を繰り返し、再割り当てのリスクがあります.

スキャンチェーンの終点に存在する


グローバル変数がscopeチェーンに存在する終点==グローバル変数は、最後の検索==すなわち、グローバル変数の検索速度が最も遅い.

ネーミングスペース汚染


javascriptの最大の問題の1つがファイルの分離であっても、グローバルスキャンを共有します.したがって、同じ名前のグローバル変数またはグローバル関数が他のファイルに存在する場合、予想外の結果が得られます...

14.3グローバル変数を無効にする方法


書くな!!変数のスキャンは狭いほど良い.グローバル変数を抑制する方法を見てみましょう.

14.3.1即時実行関数


関数定義と同時に呼び出されるインスタント実行関数は1回のみ呼び出されます.すべてのコードが即時実行関数に囲まれている場合、すべての変数は即時実行関数の領域変数になります.グローバル変数は作成されないため、リポジトリなどによく使用されます.
function foo() {
    var foo = 10;
}

console.log(foo); //[Function: foo]

==================================================================

(function foo() {
    var foo = 10;
}())
console.log(foo); //ReferenceError: foo is not defined

14.3.2名前空間オブジェクト


方法は、グローバルにネーミングスペース(namespace)のオブジェクトを作成し、グローバル変数として使用する変数をpropertyに追加することです.
var MYAPP = {}; // global 네임스페이스 객체 
MYAPP.name = 'boram'
console.log(MYAPP.name) //boram

모양도 그렇고 파이썬 딕셔너리에 추가하는 것 같네
頻繁に会わない理由=識別子の競合を防ぐためにネーミングスペースを分離しますが、ネーミングスペースオブジェクト自体がグローバル変数に割り当てられるため、あまり役に立たないように見えます.

14.3.3モジュールモード


モジュールモードはクラスを模倣し,関連する変数と関数を集合させ,直ちに実行関数でモジュールを囲む.モジュールモードはJavaScriptの強力な機能モジュールに基づいています.モジュールモードの特徴は,グローバル抑制だけでなくカプセル化も可能であることである.
モジュールモードを理解するには、まずモジュールを理解しなければなりません.はい!行ってきます.
パッケージは,オブジェクトの状態を表すPropertyとProperty,および操作可能な動作方法を組み合わせたものである.特定のプログラムやメソッドを非表示にする目的で、情報非表示と呼ばれることもあります.
JavaScriptにはpublic、private、protectedなどのアクセス制限はありません.モジュールモードは,グローバルネーミング空間汚染を防止する機能だけでなく,限られているが,情報隠蔽を実現するために用いられる.

14.3.4 ES 6モジュール


ES 6モジュールを使用すると、グローバル変数は使用できなくなります.李昊ES 6モジュールは、ファイル自体の独立したモジュールスキャンを提供する.したがって、モジュールでvarキーワードとして宣言された変数はグローバル変数ではなく、windowオブジェクトのpropertyではありません.
type="module"ツリーをscripsラベルに追加すると、ロードされたJSファイルがモジュールとして実行されます.従来のブラウザでは、操作を必要とせずに変換またはバンドルする必要があるため、モジュールバンドルパッケージ(Webpackなど)が一般的に使用されているIEを含む.