Javascript変数アップと関数アップ

7417 ワード

導入する
下のコードのセグメントはどのように出力されますか?
//    1
function func1() {
    var a = 1;
    function a() {}
    console.log(a);
}
func1();
  
//    2
function func2() {
    var a;
    function a() {}
    console.log(a);
}
func2();
運転後、コンソールの一番目console.log(a)1が出力され、2番目console.log(2)関数aが出力されます.結果は以下の通りです
[Running] node "/Users/ermao/Development/javascript_code/homework/demo.js"
1
[Function: a]

[Done] exited with code=0 in 0.044 seconds

Javascriptが実行する時、三つの段階を通ります.
  • 文法分析段階:文法分析が簡単で、エンジンがコードを確認するという低級な文法エラーがありますか?
  • プリコンパイル段階:プリコンパイルは簡単に理解すると、メモリの中にいくつかの空間を開いて、変数と関数を保存することです.
  • 実行段階を説明する:説明実行は文字通り実行コードである.
  • Javascriptの具体的な実行過程:
  • ページができたらGOグローバルオブジェクト(Global Object)(つまりwindowオブジェクト)が作成されます.
  • 最初のスクリプトファイルの読み込み;
  • スクリプトの読み込みが完了したら、文法が適法かどうかを分析する.
  • プリコンパイル開始
  • 変数宣言を検索し、GO属性としてundefinedを付与する.
  • 検索関数宣言は、GO属性として関数体に値を与えます.
  • 【注意】:
  • プリコンパイル段階で発生した変数声明と関数声明は、初期化されていません.匿名関数はプリコンパイルに参加しません.
  • 解釈実行段階でのみ変数初期化が行われる.
  • プリコンパイル2つのルール
  • 関数宣言の全体的な向上——(具体的には、関数の呼び出しと声明の位置が前であっても後であっても、システムは常に関数宣言を呼び出しの前に移動する)
  • 変数宣言の昇格——(具体的には、変数の呼び出しや声明の位置が前であっても後であっても、システムは常に声明を呼び出す前に移動します.ステートメントだけなので、値はundefinedです.)
  • プリコンパイル前奏
  • imply globalは任意の変数であり、宣言なしに値を付与すると、この変数はグローバル変数のすべてになります.(全ローカルがWindowです.)
  • 全声明のグローバル変数は、すべてwindowの属性である.var a=12・同じWindow.a = 12
  • 関数プリコンパイルが関数実行前に発生しました.
  • 変数の昇格
    この小節はJavascriptプリコンパイル段階を理解することに重点を置いています.変数はどのように作成され、また割り当てられていますか?
    //       
    var num1 = 50;
    var num2 = 100;
    
    Javascriptではコードはこのように実行されます.
    //    :     ,     (  )        。
    var num1;
    var num2;
    //    :      
    num1 = 50;
    num2 = 100;
    
    もう一つの例を通して理解してください.
    function func(){
        var m = 10;
        console.log(m);
        console.log(n);
        var n = 20;
    }
    func();
    
    実はJavascriptの目には彼はこのように動いています.
    function func(){
        var m;
        var n;
        m = 10;
        console.log(m);
        console.log(n);
        n = 20;
    }
    
    このときコンソール出力:
    [Running] node "/Users/ermao/Development/javascript_code/homework/demo.js"
    10
    undefined
    
    [Done] exited with code=0 in 0.049 seconds
    
    以下は二つの関数を同時に実行して、コンソールから出力された結果を比較します.
    function func(){
        var m = 10;
        console.log(m);
        console.log(n);
        var n = 20;
    }
    func();
    
    console.log();
    
    function funcT(){
        var m;
        var n;
        m = 10;
        console.log(m);
        console.log(n);
        n = 20;
    }
    
    funcT();
    
    このときコンソール出力の結果は以下の通りです.
    [Running] node "/Users/ermao/Development/javascript_code/homework/demo.js"
    10
    undefined
    
    10
    undefined
    
    [Done] exited with code=0 in 0.045 seconds
    
    二つの関数の実行結果は全く同じです.したがって、Javascriptは一つの変数を定義する時ではなく、宣言が完了したらすぐに値を付けます.すべての使用する変数をすべて宣言した後、変数の定義された場所に値を割り当てます.変数の宣言の過程は変数の向上です.
    変数は、宣言の昇格時には、すべての作用域の先頭に引き上げられます.次から次へと変数の割り当てが行われます.変数の割り当て時は、次から次へと値が与えられていません.変数の本来定義された位置に値が割り当てられています.元々js定義されている変数の場所は、jsがここに実行される時に、変数の割り当て操作が行われます.実行されない変数です.割り当て操作を行います.
    したがって、変数の昇格は変数の宣言であって、変数の割当値ではありません.
    関数アップ
    まず、一例を通して、関数のアップグレードの過程を体得することができます.
    function func(){
        console.log("func   ");
    }
    
    //        funcT();
    funcT();
    
    //        func();
    func();
    
    function funcT(){
        console.log("funcT   ");
    }
    
    このときコンソール出力:
    [Running] node "/Users/ermao/Development/javascript_code/homework/demo.js"
    funcT   
    func   
    
    [Done] exited with code=0 in 0.046 seconds
    
    このとき、2つの関数が成功的に実行されます.変数の昇格とは異なり、関数の昇格は1ステップで行われます.変数の昇格は2ステップで行われます.1ステップ目は変数宣言の昇格で、2ステップ目は変数の割り当てです.関数の昇格は、全体の函数を直接にスコープの最初の位置に引き上げます.
    変数の昇格と関数の昇格順
    例を通して実感する:
    console.log(a);
    var a = 1;
    console.log(a);
    function a(){
        
    }
    console.log(a);
    
    コードの実行順に基づいて、上から下に、理論的にコンソールは先に出力undefined1a(){}・となりますが、実際のコンソールは次のように出力されます.
    [Running] node "/Users/ermao/Development/javascript_code/homework/demo.js"
    #        
    [Function: a]
    #    1;
    1
    #       1
    1
    
    [Done] exited with code=0 in 0.051 seconds
    
    どうしてこのように出力しますか?実はJSの目の中で、コードはこのようです.
    //        ,  a       ,     undefined。
    var a;
    //             a undefined,  a;
    function a(){
        
    }
    //      ,        console.log()。       a
    console.log(a);
    //       var a=1 ,a=1         a     。
    a = 1;
    //          console.log()   ,   1;
    console.log(a);
    //          ,        a  。
    //      console.log()      1。
    console.log(a);
    
    関数の説明と関数式の順序
    上記では変数の昇格と関数の昇格について説明しましたが、ここでは前のセクションで述べた関数の表現を理解します.先に定義してから呼び出すこともできます.関数の説明は先に定義してから呼び出すこともできます.また、先に呼び出してから定義することもできます.
    まず例を見て、下のコンソールはどうやって出力しますか?
    console.log(testFunc);
    
    console.log(func);
    
    testFunc();
    
    func();
    
    function testFunc(){
        console.log("testFunc()   ");
    }
    
    var func = function (){
        console.log("func()   ");
    }
    
    コンソール出力:
    [Running] node "/Users/ermao/Development/javascript_code/homework/demo.js"
    [Function: testFunc]
    undefined
    testFunc()   
    /Users/ermao/Development/javascript_code/homework/demo.js:7
    func();
    ^
    
    #         ,    
    TypeError: func is not a function
        at Object. (/Users/ermao/Development/javascript_code/homework/demo.js:7:1)
        at Module._compile (internal/modules/cjs/loader.js:945:30)
        at Object.Module._extensions..js (internal/modules/cjs/loader.js:962:10)
        at Module.load (internal/modules/cjs/loader.js:798:32)
        at Function.Module._load (internal/modules/cjs/loader.js:711:12)
        at Function.Module.runMain (internal/modules/cjs/loader.js:1014:10)
        at internal/main/run_main_module.js:17:11
    
    [Done] exited with code=1 in 0.047 seconds
    
    コンソールから出力すると、Javascriptの目のコードはこのように実行されていることが分かります.
    //       
    var func; //       
    //      
    function testFunc(){
        console.log("testFunc()   ");
    }
    
    //       
    console.log(testFunc);  //        
    console.log(func);      //               ,      undefined
    
    //     
    testFunc();             //         
    func();                 //     ,                ,     。
                            //   func         
                            
    //     func    ,    。   ,       
    func = function(){
        console.log("func()   ");
    }
    
    つまり、関数の昇格は関数宣言にのみ適用され、関数式には適用されません.簡単に言えば、事前コンパイルのアップグレード段階では変数として昇格され、変数の割り当ては行われません.
    矢印関数は正常に動作しますか?以下のコードを参照してください.
    console.log(testFunc);
    
    console.log(func);
    
    testFunc();
    
    func();
    
    function testFunc(){
        console.log("testFunc()   ");
    }
    
    var func = () => {
        console.log("func()   ");
    }
    
    コンソールの出力は以下の通りです.原因は?
    [Running] node "/Users/ermao/Development/javascript_code/homework/tempCodeRunnerFile.js"
    [Function: testFunc]
    undefined
    testFunc()   
    /Users/ermao/Development/javascript_code/homework/tempCodeRunnerFile.js:7
    func();
    ^
    
    TypeError: func is not a function
        at Object. (/Users/ermao/Development/javascript_code/homework/tempCodeRunnerFile.js:7:1)
        at Module._compile (internal/modules/cjs/loader.js:945:30)
        at Object.Module._extensions..js (internal/modules/cjs/loader.js:962:10)
        at Module.load (internal/modules/cjs/loader.js:798:32)
        at Function.Module._load (internal/modules/cjs/loader.js:711:12)
        at Function.Module.runMain (internal/modules/cjs/loader.js:1014:10)
        at internal/main/run_main_module.js:17:11
    
    [Done] exited with code=1 in 0.045 seconds