全域と地域スキャン、護衛


Scope(有効範囲)


scopeはJavaScriptを含むすべてのプログラミング言語の基本概念である.関数と変数は、グローバルまたはコードブロック、関数内で宣言され、宣言された場所に基づいて有効な範囲があります.これがスキャンです.他のコードが自分を参照できるかどうかを決定する場所を宣言します.

そういんはんい


JavaScriptでは、スキャンはグローバルスキャンとゾーンスキャンに分けられます.
  • 全局計
    一番外側の顕微鏡.グローバル範囲で宣言される変数は、グローバル変数です.キーワードvarとして宣言されたグローバル変数は、グローバルscopeに格納され、consoleとして使用されます.log(window.変数名)でアクセスできますが、let、constと宣言されたグローバル変数はグローバルスキャンには格納されず、スクリプトスキャンに格納されます!
    https://stackoverflow.com/questions/40685277/what-is-the-purpose-of-the-script-scope

  • ゾーンスキャン
    既存のvarキーを使用する場合、領域スキャンは関数レベルスキャンのみですが、ECMAScript 6に導入されたletキーを使用するとブロックレベルスキャンが使用できます.ゾーンスキャンで宣言される変数は、ゾーン変数です.領域スキャンを離れると、どのキーワード(var、let、const)として宣言されても、その領域スキャンの領域変数は削除されます.(削除されているため、エリア範囲から値を取得できません!)
  • 関数レベルスキャン(機能レベルscope)
    関数内で宣言された変数は、関数内でのみ有効であり、関数外で参照できません.すなわち,関数内部宣言の変数は領域変数であり,関数外部宣言の変数はすべてグローバル変数である.
  • ブロックレベルスキャン(Block-level scope)
    すべてのコードブロック(関数、if文、for文、while文、try/catch文など)で宣言された変数は、コードブロック内でのみ有効であり、コードブロックの外部参照はできません.すなわち,コードブロック内部で宣言される変数は領域変数である.
  • var


    ES 5まで変数を宣言する方法はvarキーワードを用いる.varは以下の特徴を有し、letとconstを使用することを提案し、理由は以下の通りである.
  • ブロック級のスキャナーを無視します.(=関数レベルスキャン)
  • 関数の外部で生成される変数はすべてグローバル変数です.
  • for文の変数宣言で宣言された変数は、文コードブロックの外部で参照できます.
  • for(var i=0;i<5;i++)
    {
      console.log(i); //1,2,3,4,5
    }
    console.log(i); //5
    
    var는 블록레벨 스코프를 무시하므로, var i=0으로 선언된 변수 i는 블록코드 내에서만 유효한 게 아니라 전역변수처럼
    사용되는 것이다. 따라서 다음과 같이 코드블록 밖의 콘솔창에서 i를 출력해도 reference error를 출력하지 않는다.
  • varキーワードの省略を許可
    グローバル変数と同じ名前の変数をvarキーなしで関数レベルの範囲に宣言した場合、新しい変数を宣言するのではなく、グローバル変数値を再割り当てします.
  • i = 3;
    function show(){
      i = 5;
      console.log(i); //5
    }
    show();
    console.log(i); //5
    
    위의 코드 실행 순서는 다음과 같다.
    1. 1번째 줄에 의해 전역객체 윈도우에 전역변수 i=3 할당
    2. 6번째 줄에 의해 show()를 실행시킨다
       2-1. 3번째 줄에 의해 전역변수 i=5로 재할당
       2-2. 4번째 줄에 의해 콘솔창에 5 출력하고 함수 종료
    3. 7번째 줄에 의해 전역객체에 저장된 i=5 출력 

  • 変数の繰り返し宣言を許可
    同じ名前の変数を再宣言すると、letとconstはSyntaxError:Identifiier"..."を取得しません.宣言されたエラーを出力します.変数の繰り返し宣言を許可すると、既存の宣言の値が上書きされ、コード全体に問題が発生する可能性があります.

  • がんばって
    JavaScriptはvar、let、const、function、classなどの宣言をサポートします.ホイスティンは、宣言を相応のスコフの前に移したような動作の特徴だ.以下の場合、変数dは円弧化されるので、1を出力することができる.
  • d = 1;
    console.log(d); //1
    var d;
    
    console.log(e); //undefined
    var e;

    letとconst


    前述した変数宣言方式varの欠点を保護するために,ES 6構文にletとconstを追加した.
    varとconstを比較すると以下のようになります.
    再宣言(重複宣言)再割当番号ポーリングvar 110

  • letおよびconstは、再宣言時にUncaught SyntaxError: Identifier '변수명' has already been declaredエラーが発生しました.

  • constは再割り当て時にエラーUncaught TypeError: Assignment to constant variable.が発生しました.

  • letとcontもエスケープされたが,宣言と初期化段階の間にTDZ(Temporal Dead Zone)が存在した.
  • がんばって


    護衛過程.


  • 宣言(宣言フェーズ)
    変数を実行コンテキストの「変数オブジェクト」(Variable Object)に登録します.この変数オブジェクトはscope参照のオブジェクトになります.

  • 初期化フェーズ
    メモリに、変数オブジェクト(Variable Object)に登録されている変数があることを確認します.この段階では、変数はundefinedに初期化される.

  • わりあてundefinedに初期化された変数に実際の値を割り当てます.
  • varキーワードとして宣言された変数は、宣言フェーズと初期化フェーズを一度に完了します.すなわち、scopeに変数を登録(宣言)し、メモリに変数のスペースを残してundefinedに初期化する.したがって、変数宣言文の前に変数に近づいても、scopeに変数がすでに存在するため、undefinedを返します.その後、変数付与文に達すると、値が割り当てられます.
    console.log(a); //undefined
    //이 단계에서 이미 a가 호이스팅되어 전역객체에 a:undefined로 저장되어 있다
    var a = 3; 
    
    console.log(b); //undefined
    var b;
    letキーワード宣言の変数は、宣言と初期化によって別々に行われます.すなわち,scopeには変数が登録されているが,コードブロックの先頭から初期化点まで一時死角(TDZ)が存在する.初期化は変数宣言に到達したときに行われます.
    console.log(b); //Uncaught ReferenceError: Cannot access 'b' before initialization
    let b = 33;
    
    let c = 100;
    if(true){
      console.log(c); //Uncaught ReferenceError: Cannot access 'c' before initialization
      let c = 300;
    }
    1つ目の場合、bは初期化されていないため、メモリが取得できないかdefinedが割り当てられていないため、参照エラーが出力されます.2つ目のケースは、グローバル変数として宣言されたcが存在するが、もう1つの地域変数として宣言されたcがエスケープされTDZに留まっているため、コンソールに100を書き込むことなく参照エラーが発生する.
    let foo = 1;
    {
      console.log(foo); //Uncaught ReferenceError: Cannot access 'foo' before initialization
      let foo = 2;
    }
    fooはグローバル変数として宣言されるため、3行目は1を出力する可能性がありますが、実際には参照エラーが出力されます.
    ブロックレベルスキャンアンfooは領域変数です.従って、領域変数fooも対応する走査で遮断され、初期化点の死角地帯に一時的に陥る.(初期化は変数宣言に到達したときに完了します.)すなわち、グローバル変数に同じ名前の変数が割り当てられていても、ブロックレベルスキャン内の領域変数は再びエスケープされるため、先に変数を割り当てる必要がある.
    constキーワードとして宣言される変数は、宣言と割り当て構文を同時に作成する必要があります.宣言のみを記述すると、次のSyntaxErrorが発生します.
    const a;
    //Uncaught SyntaxError: Missing initializer in const declaration
    匿名関数はブロックされません.スクリプト内のどの場所で宣言しても、シンボル関数を呼び出すことで関数を呼び出すことができます.ただし、変数に割り当てられた匿名関数はハイライトされません.ページがレンダリングされる前に、ブラウザで使用されるメモリが多ければ多いほど、関数で使用される変数は関数レベルのスキャンで宣言され、匿名の関数を使用してページがレンダリングされないようにすることができます.
    console.log(example()); //10
    function example(){
        const a = 10;
        return a;
    }
    
    console.log(func()); //Uncaught ReferenceError: func is not defined
    const func = function(){
        const b = 10;
        return b;
    }
    
    console.log(func()); //Uncaught ReferenceError: func is not defined
    const func = () => {
        const c = 10;
        return c;
    }

    reference

  • https://poiemaweb.com/es6-block-scope
  • https://www.youtube.com/watch?v=ppMlvGMT2qE