JavaScriptの変数アップ機構

4630 ワード

変数の昇格
JavaScriptの変数アップグレードには、varで宣言された変数とfunctionで宣言された変数の2つがあります.
varで宣言する変数
まず次のコードを見てみます.aの値はいくらですか?
コード1

console.log(a);

var a;
以前のプログラミング言語の考え方から見れば、コードは上から下まで運行しています.このような考え方では、第2行まで実行した場合、変数aはまだ定義されていないので、エラーが発生します.
しかし、実際の答えはa is not definedです.
はい、疑いを抱いて、次のコードを見ます.
var a;
console.log(a);
私たちはこの二つのコードが同じであることを発見しました.また新しい問題があります.undefinedがあっても大丈夫ですか?その答えはいつもvar aです.やっと変数が向上するという錯覚を引き起こしました.コード3を書きました.
コード3
console.log(a);
はい、やっと間違えました.ですから、これはundefinedコードが上から下まで実行されたのではないことを証明しました.少なくとも表面から見れば、上のように見えます.
そこでコードを見ます.
コード4
console.log(a);
var a = 2;
変数が上昇しているので、答えは2ですが、実際にはjavaScript、whyですか?
この時、文法分析やコード生成などの汚い仕事を担当するコンパイラをお願いします.
コンパイラは、undefinedを参照してください.2つのステートメントとして見なされます.var a = 2;var a;と、最初のステートメントはコンパイル段階で行われ、第2のステートメントは元の場所で実行段階を待っています.
つまり上のコードは、下のコードになります.
var a;
console.log(a);
a = 2;
最終的にはa = 2です.
はい、私はくどいです.このコードを見てください.
コード5
a = 2;
var a;
console.log(a);
このコードの実行時の本当の順序と答えはもう知っていると思います.そうです.答えは2です.しかし、2行目を注釈してもいいです.答えは2です.しかし、これは変数のアップグレードと関係がありません.厳格モードと非厳格モードの鍋です.非厳格モードで開発者が声明変数のキーワードを使わなくてもいいです.しかし、厳密なモードではいけません.間違いを報告します.
functionで宣言した変数undefinedと同様に、varによって宣言された変数は依然として向上します.
log(5);

function log(mes){
    console.log(mes)
}
前の変数の昇格の理解によって、このコードの本当の順序はこうなります.
function log(mes){
    console.log(mes)
}

log(5);
はい、正しいです.次のコードを見ます.
log(5);

var log = function(mes){
    console.log(mes)
}
エラーを報告しました.function、ここからこの関数式は昇格されません.関数宣言だけが昇格されます.一番前にコードlog is not a functionを追加してみたら、console.log(log)が先に出力されます.
ここの本当の順番は?
var log;
log(); //        log    ,     ,          ,     ,        。
log = function(mes){
    console.log(mes)
}
functionで変数をvarで宣言します.
私たちはundefined宣言の変数が上昇することを知っていますが、どの程度まで引き上げるかは分かりません.
その前にコードを見てください.
var a = 4;

function foo(){
    var a = 5;
    console.log(a);

}
foo();

console.log(a)
答えは5,4です.まず5を出力して、4を出力します.varで宣言した変数は関数のスコープがあるので、fooの中のaとfooの外のaは何の関係もありません.
コードを変更します

function foo(){
    a = 5
    console.log(a);
    var a;
}
foo();

console.log(a)
答えは5、a is not definedです.
第4行コード出力5、第9行エラー.
この場合、変数の上昇は変数の存在するスコープの上部だけになり、親レベルのスコープまでは上昇しません.
変数が上昇すると、自分のいるスコープの上に変数が上がるだけという結論が得られます.
関数優先varvarの変数でアップグレード機能がある以上、同じ変数を使ってこの二つの宣言がどうなるかは、タイトルを見れば分かります.関数優先です.
コードを具体的に見てください
foo();

var foo;

function foo(){
    console.log(1)
}

foo = function(){
    console.log(2)
}
答えは1です
このコードは実はこのようです.
function foo(){
    console.log(1)
}

foo();// 1

foo = function(){
    console.log(2)
}
よく見ると、functionはなくなりました.間違いなく、エンジンに無視されました.繰り返し声明を出したので、それを捨てました.
はい、var foo;によって宣言された変数は関数に比べて宣言されない以上、関数によって宣言され、何度も同じ変数を宣言します.

foo()
function foo(){
    console.log(1);
}
foo()
function foo(){
    console.log(2);
}
foo()
function foo(){
    console.log(3);
}

foo()
varは3回、4回の呼び出しを宣言しました.毎回の呼び出しの結果は3です.最後の関数宣言は前の関数宣言を上書きします.
しかし、fooは、自分の存在感を証明する必要があると思います.

foo()
function foo(){
    console.log(1);
}
var foo;
foo()
foo = function(){
    console.log(2);
}
foo()
function foo(){
    console.log(3);
}

foo()

よく見てください.中間のコードが変更されました.順次3、3、2、2を出力します.varは無視されているが、以下の関数はまだ有用であり、このコードはこのように見えることができる.
function foo(){
    console.log(3);
}

foo();//3
foo();//3
foo = function(){
    console.log(2);
}
foo();//2
foo();//2

一般ブロック内の宣言関数
以前はスコープ宣言関数でしたが、今はブロック内の宣言関数に来ます.
function foo(){

    console.log(b); // undefined
    b(); //TypeError: b is not a function

    var a = true;

    if(a){
        function b(){
            console.log(2)
        }
        //              
        // var b = function(){
  //           console.log(2)
  //       }
    }
    //b() -->       

}

foo()
上から見ると、bはvar fooであり、この変数があることを証明していますが、関数ではなく、この場合は関数式と同じです.
締め括りをつける
  • 昇格関数宣言昇格と変数宣言昇格
  • 宣言変数用undefined、宣言関数用var
  • 変数がアップグレードされると、自分のいるスコープのトップ
  • に変数がアップグレードされます.
  • 関数式には向上のメカニズムがありません.
  • 関数宣言と変数宣言が同一の識別子を同時に宣言する場合、関数宣言優先
  • 複数の関数が同一の識別子を宣言した場合、最後の声明は前のステートメント
  • をカバーする.