ES 6のブロックレベルのスコープ

10372 ワード

個人サイトへようこそ
スコープ
作用領域とは変数が作用する範囲を指し、Javascriptには2つの作用領域があります.
  • グローバルスコープ
  • 関数領域
  • 変数の昇格
    変数アップグレード(Hoisting)は、Javascriptで実行されるコンテキスト(特に作成と実行段階)の動作方式の認識であると考えられる.具体的な表現は、すべてのvar宣言による変数が現在のスコープの先頭に引き上げられます.
    function foo() {
        console.log(temp); 
    }
    
    function bar() {
        console.log(temp);  
        var temp;
    }
    
    foo(); // ReferenceError: temp is not defined
    bar(); // undefined
    
    varで宣言したのは間違いではないと見られます.実は関数バーは
    function bar() {
        var temp;
        console.log(temp);
    }
    
    ほとんどのC言語文法の言語はブロックレベルの機能領域を持っています.コードブロックで定義されているすべての変数は、コードブロックの外部では見られません.コードブロックに定義されている変数は、コードブロックが実行された後に解放されます.これはいいことです
    悪いことに、Javascriptのコードはブロックレベルのスコープをサポートしているようですが、実際にはJavascriptはサポートしていません.この混淆点は間違いのもとになるかもしれません.
    従って、ES 6において、letおよびconstがブロックレベルのロールドメインをサポートするように規定されている.しかし、本当に向上していないのではないでしょうか?
    let
    letは「より完璧なvar」と理解できます.使い方は簡単です.
    let foo = 3;
    
    使用方法は基本的にはvarと同じであり、声明の変数はそのブロックとサブブロックの中だけで利用可能であり、これもvarと同じである.両者の間の最も主要な違いは、var宣言の変数のスコープが閉鎖関数全体であることにある.
    function foo() {
        if(true) {
            var temp = 5;
             console.log(temp);
        }
        
        console.log(temp);
    }
    
    function bar() {
        if(true) {
            let temp = 5;
            console.log(temp);
        }
        
        console.log(temp);
    }
    
    foo(); // 5   5
    bar(); // 5   "ReferenceError: temp is not defined
    
    let宣言の変数のスコープは、外層関数全体ではなく外層ブロックにすぎない.
    この特性を利用して、直ちに関数(IIIIFE)を実行する代わりに使用できます.
    // IIFE
    (function(){
        var temp = xxx;
        /*
            other code
        */
    }())
    
    //   
    {
        let temp = xxx;
        /*
            other code
        */
    }
    
    コンサート
    constの使い方はletと同じですが、constは必ず初期化し、初期化しないとエラーが発生します.
    const temp = 4;
    
    //        
    const t; // SyntaxError: Missing initializer in const declaration
    
    constはブロックレベルのスコープで、constはletの語義と似ています.定数を宣言するために用いられます.一旦声明したら、変更できません.なお、const宣言の変数記録は、ポインタであり、変更できないものはポインタであり、constが宣言しているものが対象であれば、オブジェクトの内容は変更可能である.
    //           
    const PI = 3.14;
    PI = 3.1415926; // TypeError: Assignment to constant variable.
    
    //             obj      ,      
    const obj = { foo: 2 };
    obj.bar = 3;
    console.log(obj); // {foo: 2, bar: 3}
    
    一時死地
    letまたはconst宣言を使用する変数は、ステートメントが到着する前にこの変数にアクセスするとエラーが発生し、常に安全だと考えていたtypeofすら安全ではない.
    // TDZ1
    function foo() {
        // TDZ   
        console.log(typeof temp);
        let temp = 5; // TDZ   
    }
    
    foo(); // ReferenceError: temp is not defined
    
    エラーはReferenceErrorであり、var声明を使用すれば、temp出力はundefinedであり、let宣言の変数のブロックの最初の行から、ステートメント変数の間のこの領域までは一時的なデッドエリア(TDZ)と呼ばれています.このエリアでこれらの変数を使うとエラーが発生します.
    // TDZ2
    function bar() {
        console.log(typeof temp);
    }
    
    bar(); // undefined
    
    上の二つの例を見てよく考えたら、何か思いつきがありますか?
    関数の中でletでtempを宣言していない時、tempはundefinedで、道理を説いてlet声明の前でtempであるべきですが、foo関数はエラーを報告して、let声明の地方に到着していないにもかかわらず、letを使う前にすでに役割を果たしました.これは、実はletもアップグレードされています.(このアップグレードはvarのようなアップグレードではなく、影響があります.)TDZの使用時にエラーが発生しました.undefinedではありません.
    実際には、JSエンジンが下のコードブロックを見て変数宣言があると、var宣言の変数に対して、声明を関数または大域作用領域のトップに引き上げ、letまたはconstに対しては一時的なデッドゾーンに置く.一時的にデッドタイム内で変数にアクセスしようとすると、いずれも「ランタイム」エラーを引き起こします.変数の宣言文に実行した場合のみ、この変数は一時的な不感から取り除かれ、安全に使用できます.
    繰り返し宣言を禁止する
    同じブロック内で、letとconstは同じ識別子を宣言できない.禁止されている場合は以下を含む.
  • letまたはconstおよびletまたはconst
  • varとletまたはconst
  • 関数パラメータとletまたはconst
  • // let   let
    let foo = 1;
    let foo = 2;
    
    // let   const
    let foo = 1;
    const foo = 2;
    
    // var   let
    var foo = 1;
    let foo = 2;
    
    //       let
    function bar(foo) {
        let foo = 1;
    }
    
    以上の状況はすべてSyntxErrorに報告します.ただし、ネストされたスコープ内でletを使用して同じ変数が許容されることを宣言します.
    var foo = 1;
    
    {
        //     
        let = 2;
        // other code
    }
    
    また、letおよびconstはブロックレベルの作用領域であるため、宣言された変数は現在のブロックが使用された後に解放されるので、同じ識別子を使っても外部作用領域の変数をカバーしないが、varは外部作用領域の変数をカバーする.
    function foo() {
        var bar = 1;
        {
            let bar = 2;
        }
        
        console.log(bar);
    }
    
    function zoo() {
        var bar = 1;
        {
            var bar = 2;
        }
        
        console.log(bar);
    }
    
    foo(); // 1
    zoo(); // 2
    
    ベストな実践
    ES 6の発展段階において、広く認知されている変数宣言方式は、標準ではvarではなくletを使用すべきである.多くのJS開発者にとって、letの行動方式はvar本来のあり方であるため、varに直接letを代用するのが論理的である.この場合には、保護が必要な変数に対してconstを使用してください.
    デフォルトではconstを使いますが、変数値が変更されることを知っている場合のみletを使います.これはコードの中で基本的なレベルの不変性を確保でき、ある種類のエラーを防止するのに役立ちます.
    思考問題
    二つの思考問題はコメントの中で答えられます.後で私の考えをコメントに載せます.
    //     1
    switch (x) {
      case 0:
        let foo;
        break;
        
      case 1:
        let foo; // TypeError for redeclaration.
        break;
    }
    
    //     2
    function bar(){
       var foo = 1;
       if (true) {
          let foo = (foo + 2); 
       }
    }
    bar();
    
    皆さん、こんにちは、私は桃翁です.自分で代弁します.
    個人のWeChat公式アカウント