ES 6——let/const/var使用シーンと区別

5772 ワード

前言
letとconstはES 6に追加されたコマンドで、ES 5でvarコマンドを使用して変数を宣言するいくつかの問題を解決するために発生したもので、varコマンドのいくつかの不合理な問題を見てみましょう.
varの問題
varには主に以下のような不合理な点があります.
  • ブロックレベルの役割ドメインがない
  • 繰り返し宣言
  • グローバル役割ドメイン
  • をバインド
  • 変数アップ
  • 問題1:ブロックレベル役割ドメインES 5がないのはグローバル役割ドメインと関数役割ドメインのみであり、ブロックレベル役割ドメインはない.ES 6の前に、最も一般的な修復方法はIIFE(Immediately Invoked Function Expression)を使用することであり、直ちに呼び出される関数式、すなわち、関数を宣言しながら直ちにこの関数を呼び出すことを意味する).eg:
    for(var i=0;i<5;i++){
        setTimeout(function(){
            console.log(i);
        },1000)
    } //5555
    

    IIFE解決
    for (var i = 0; i < 5; i++) {
    ​    (function(i) {
    ​        setTimeout(function() { 
    ​          console.log(i); 
    ​        }, 1000);
    ​    })(i);
    }//01234
    

    しかしletとconstの発明は私たちにもっと簡単な修復方法をもたらした.ループに新しい変数環境が導入されただけでなく、反復のたびにこのような新しい役割ドメインが作成されます.これが私たちが直ちに実行する関数式を使用するときにしたことletの解決です.
    for(let i = 0; i < 5; i++) {
        setTimeout(function() {
          console.log(i);
        }, 1000)
    }
    

    問題2:繰り返し宣言varは同じ識別子の変数を繰り返し宣言することができ、多くの言語では同じ役割ドメインで同じ変数を複数回宣言するのは違法であるが、ES 5でvarコマンドを使用して繰り返し宣言するのは問題ない.letは許されない.eg:
         var a = 1;console.log(a); //1
    ​    var a = 2;
    ​    console.log(a); // 2
    ​    var a = 3;
    ​    console.log(a); //3
    

    質問3:グローバル役割ドメインをバインドグローバル役割ドメインの下でvarコマンドで変数を宣言すると、グローバルオブジェクトのプロパティegとして新しいグローバル変数が作成されます.
     `````var a = 1;
    ​     console.log(window)
    

    質問4:変数昇格変数昇格とは変数宣言の昇格を指し、変数の初期化と付与は昇格せず、JavaScriptは役割ドメイン内のすべての変数と関数を関数の上部宣言egに言及する.
     console.log(foo) //undifined
     var foo = 123
    

    fooは実は呼び出す前に宣言されていますが、初期化されていません.letにとって、状況は少し違います:eg:
     console.log(aLet)  
    // Uncaught ReferenceError: Cannot access 'aLet' before initialization
    let aLet = 2
    

    注意:let/const宣言の前に対応する変数と定数にアクセスすると、ReferenceErrorエラーが放出されます.ただしvar宣言の前に対応する変数にアクセスするとundefinedが得られます
    ES 6規格のlet/const宣言の章13.3.1によると、let/const宣言の変数は、それらに含まれる文法環境(Lexical Environment)がインスタンス化されたときに作成されるが、変数(et/const)の文法バインド(LexicalBinding)が求められた演算後(初期化)にのみアクセスできるという.プログラムの制御フローが新しい役割ドメイン(module,functionまたはblock役割ドメイン)でインスタンス化されると、この役割ドメインにおけるlet/constで宣言された変数は、まず役割ドメインで作成されるが、この場合は文法的バインド、すなわち宣言文の評価演算が行われていないため、アクセスできず、アクセスがエラーを投げ出す.したがって,この実行フローが役割ドメインに入ると変数が作成され,変数がアクセス可能になるまでの期間をTDZ(一時的デッドゾーン)と呼ぶ.
    TDZは最初はconstのために設計されたが,後のletの設計も一致した.
    以上の説明から,let/constで宣言される変数も,昇格(hoist)の役割を果たす.昇格はJS言語における変数宣言の基本的な特性であるが,TDZの役割のためvarを用いて変数を宣言するのではなくundefinedが得られるだけであり,現在ではReferenceErrorエラーが直接投げ出され,実行中に発生するエラーであることが明らかになった.eg:
     let x = 'outer value'
     (function () {
        //       TDZ for x
        console.log(x) // TDZ    ,  ReferenceError  
        let x = 'inner value' //  x     ,     TDZ for x
     }())
    

    例のIIFEの関数役割ドメインでは、変数xが役割ドメインの中で先に関数領域の一番上に上げられるが、この場合TDZが発生し、プログラムフローがxの宣言文まで実行されていない場合、TDZの役割の間として計算され、このときxの値にアクセスすると、ReferenceErrorエラーが投げ出される.
    const
    特長
    1.constは一般的に定数を宣言するためにのみ使用され、宣言と同時に即時初期化(Missing initializer in const declaration構文エラー)eg:
    const y; // Missing initializer in const declaration
    

    2.宣言された定数は変更できません.そうしないと、エラーが発生します(Assignment to constant variable.(一定変数を指定します.))注:オブジェクト、配列(参照タイプデータ)を宣言するとき、オブジェクトの属性名と属性値は追加、変更できます.変数名が指すアドレスが変わらないことを保証します.別のオブジェクトを再び指すことはできません.オブジェクトを書き換えることはできません.eg:
     const x = 1; 
     x = 2;  // Uncaught TypeError: Assignment to constant()
     const obj = {
       name: 1
     }
     obj.name = 2;
     obj.name1 = 3;
     console.log(obj) //{name: 2, name1: 3}
     obj = { name: 3 } // Assignment to constant variable.
    

    3.ブロックレベルの役割ドメインeg:
     {
      const age = 17;
     }
    age; //ReferenceError: age is not defined
    

    **4.一時的なデッドスペースが存在し、宣言後にのみ**を呼び出すことができます.
    練習問題:
    1.1
    let a;
    const a
    

    結果:
    let a; //    
    const a //     Missing initializer in const declaration
    

    1.2
    let user = {name:'Lucy',age:17};
    const USER_INFO = user;
    console.log(user)
    console.log(USER_INFO)
    
    user.age = 32;
    console.log(user)
    console.log(USER_INFO)
    

    結果:
    {name:‘Lucy’,age:17}
    {name:‘Lucy’,age:17}
    {name:‘Lucy’,age:32}
    {name:‘Lucy’,age:32}
    
    

    1.3
         let a = 'aaa';
    ​    console.log(a);  
    ​    console.log(window.a);  
    ​    var b = 'bbb';
    ​    console.log(b);  
    ​    console.log(window.b);  
    ​    c = 'ccc';
    ​    console.log(c);  
    ​    console.log(window.c);
    

    結果:
       aaa
       undefined
       bbb
       bbb
       ccc
       ccc
    

    1.4
    var a = 1; 
    b = 2; 
    delete a; 
    delete b;
    console.log(window)
    

    結果:delete a;//var定義の変数を使用して、削除できません.理由:var文を使用して追加したwindowプロパティにはconfigurableというプロパティがあり、その値はfalseに設定されています.delete b;//削除delete window.c;//削除
    1.5
    for (var i = 0; i < 3; i++) {
       console.log(i)
    }
    console.log(i)
    
    for (let j = 0; j < 3; j++) {
       console.log(j)
    }
    console.log(j)
    

    結果:
    0 1 2
    3
    
    0 1 2
    j is not defined
    

    1.6
    for (var i = 0; i < 3; i++) {
        let i = 'bbb';
        console.log(i);
    }
    for (let j = 0; j < 3; j++) {
        var j = 'aaa';
        console.log(j);
    }
    

    結果:bbb bbb bbb Identifier'j'has already been declared.(識別子「i」が宣言された)1.7
    var a = [];
    for (var i = 0; i < 10; i++) {
     console.log(i);
     a[i] = function () {
       console.log(i);  //      ,for        ,i    10
     };
    }
    a[6]();
    

    結果:0 1 2 3 4 5 6 7 8 9 10 1.8
    for (var i = 1; i <= 5; i++) {
        (function() {
            setTimeout( function timer() {
                console.log(i);
            },i*1000 );
        })();
    }
    

    結果:66666
    関連面接問題リンク:https://blog.csdn.net/qq_37024887/article/details/106784068