javascriptコア--解析プロセス

6843 ワード

1.javascript解析過程
一つの文書ストリームに複数のスクリプトコードセグメント(scriptタグで区切られたjsコードまたは導入されたjsファイル)が含まれている場合、それらの実行順序は以下の通りです.
ステップ1.最初の読み込み
コードセグメント(js実行エンジンは、プログラムを行単位で実行するのではなく、セグメント単位で分析して実行する)
ステップ2.する
文法解析では、エラーがあったら文法エラー(括弧の不一致など)を報告し、ステップ5に進みます.
ステップ3.var変数とfunction定義を“
事前解析」(正確な声明だけを解析するので、エラーは永遠に発生しません.)
ステップ4.コードセグメントを実行し、
エラーメッセージエラー(変数未定義など)
ステップ5.次のコードセグメントがある場合は、次のコードセグメントを読み込み、手順2を繰り返します.
ステップ6.終了
javascript解析シミュレーション
1.解析待ちのjs

/*  (window)       */
var i = 1,j = 2,k = 3;
function a(o,p,x,q){
    var x = 4;
    alert(i);

    //    a       b,     i,y
    function b(r,s) {
        var i = 11,y = 5;
        alert(i);
        
       //   b       c,     z
       function c(t){
           var z = 6;
           alert(i);
        };
        
       // b          d
        var d = function(){
            alert(y);
        };
        c(60);
        d();
    };
    b(40,50);
}
a(10,20,30);

2.分析ツリーの作成
上のコードは簡単です.大域変数と大域方法を定義してから、方法の中で局部変数と局部方法を定義します.今はJSインタプリタがこのコードを読み込んで解析を開始します.前に述べたJSエンジンは先に文法分析と事前解析によって語法分析ツリーを得ます.文法分析ツリーの長さについては、どのような情報がありますか?
以下は簡単な構造で、JSオブジェクト(各オブジェクト間の引用関係を明確に示すために、ここのは偽オブジェクト表現だけで、実行できないかもしれません)で文法分析ツリーを記述します.

/**
*            ,  function       
*/
var SyntaxTree = {
        //               
    window: {
        variables:{
            i:{ value:1},
            j:{ value:2},
            k:{ value:3}
        },
        functions:{
            a: this.a
        }
    },
 
    a:{
        variables:{
            x:'undefined'
        },
        functions:{
            b: this.b
        },
        scope: this.window
    },
 
    b:{
        variables:{
            y:'undefined'
        },
        functions:{
            c: this.c,
            d: this.d
        },
        scope: this.a
    },
 
    c:{
        variables:{
            z:'undefined'
        },
        functions:{},
        scope: this.b
    },
 
    d:{
        variables:{},
        functions:{},
        scope: {
           myname:d,
           scope: this.b
        }
    }
};
上には文法分析ツリーについての簡単な表現があります.前に分析したように、文法分析ツリーは主に各functionにおける変数セット、方法セット(functions)と作用領域(scope)を記録しています.
構文解析ツリーのポイント
変数セットでは、
変数定義のみで変数値がありません.このときの変数値はすべて「undefined」です.
スコープ(scope)は、語法によってドメインの特徴が働きます.
各変数のスコープは、実行時の環境によっては変化しないことが明らかになりました.「どういう意味ですか?私たちは常に一つの方法をリセットし、別の方法で実行します.実行する時、方法の変数の作用域は方法によって定義される時の作用域です.実はここで言いたいのですが、どんなに複雑で遠いところでこの方法を実行しても、変数が訪問されるかどうかを最終的に判断するということです.」方法定義時の場所検証】
スコープ確立規則:
    a.関数宣言と匿名関数表現にとって、[scope]は作成時のスコープです.
    b.名前のある関数式については、「scope」の先端に新しいJSオブジェクト(つまりObject.prototypeを継承しています)があり、このオブジェクトには2つの属性があり、1つ目は自分の名前、2つ目は定義のスコープ、1つ目は関数内のコードが自分の関数名に誤ってアクセスできるように再帰します.
3、実行環境
構文解析が完了し、コードの実行を開始します.各方法を呼び出すと、JSエンジンは自動的に実行環境とアクティブオブジェクトを作成します.これらは方法の実例と同じライフサイクルを維持し、方法の実行に必要な実行サポートを提供します.(方法を実行する時に活動対象が生成されるのが道理です.プレゼンテーションを容易にするために、ここで一気にあらゆる方法の活動対象が定義されています.)具体的には次のようになります.

/**
*     :            
*/
var ExecutionContext = {
    window: {
        type: 'global',
        name: 'global',
        body: ActiveObject.window
    },
 
    a:{
        type: 'function',
        name: 'a',
        body: ActiveObject.a,
        scopeChain: this.window.body
    },
 
    b:{
        type: 'function',
        name: 'b',
        body: ActiveObject.b,
        scopeChain: this.a.body
    },
 
    c:{
        type: 'function',
        name: 'c',
        body: ActiveObject.c,
        scopeChain: this.b.body
    },
 
    d:{
        type: 'function',
        name: 'd',
        body: ActiveObject.d,
        scopeChain: this.b.body
    }
}
上記の各方法の実行環境には、それぞれの方法の種類、方法名、アクティビティオブジェクト(ActiveObject)、作用ドメインチェーン(scopeChin)などの情報が格納されており、そのポイントは以下の通りである.
body属性は、現在の方法の活動対象を直接指します.
scopeCharin属性、スコープチェーンは、構文解析ツリー内の現在の方法に対応しています.
scope属性は、scopeに対応する方法の活動対象を指し、変数検索はこのチェーンに従って検索されます.
4.活動対象

/**
*     :              
*/
var ActiveObject = {
        window: {
        variables:{
            i: { value:1},
            j: { value:2},
            k: { value:3}
        },
        functions:{
            a: this.a
        }
    },
 
    a:{
        variables:{
            x: {value:4}
        },
        functions:{
            b: SyntaxTree.b
        },
        parameters:{
            o: {value: 10},
            p: {value: 20},
            x: this.variables.x,
            q: 'undefined'
        },
        arguments:[this.parameters.o,this.parameters.p,this.parameters.x]
    },
 
    b:{
        variables:{
            y:{ value:5}
        },
        functions:{
            c: SyntaxTree.c,
            d: SyntaxTree.d
        },
        parameters:{
            r:{value:40},
            s:{value:50}
        },
        arguments:[this.parameters.r,this.parameters.s]
    },
 
    c:{
        variables:{
            z:{ value:6}
        },
        functions:{},
        parameters:{
            u:{value:70}
        },
        arguments:[this.parameters.u]
    },
 
    d:{
        variables:{},
        functions:{},
        parameters:{},
        arguments:[]
    }
}
上記の各活動オブジェクトは、それぞれの方法の内部変数セット、埋め込み関数セット、形参、実参などの実行に必要な情報を格納しています.
アクティブオブジェクトを作成して、構文解析ツリーのコピー方法の内部変数セット(variables)と埋め込み関数セット(functions)を作成します.
メソッドは実行を開始し、アクティブオブジェクト内の内部変数セットはすべてundefinedにリセットされます.
イメージパラメータとオブジェオブジェクトを作成し、
同じ名前の実装では、イメージと変数の間には【参照】関係があります.
メソッド内の割当文を実行すると、変数セットの変数に対して値付け処理が行われます.
変数検索規則は、まず現在実行されている環境のActiveObjectから探します.見つけられなかった場合は、実行環境の属性に従います.
Scope Charinが指すActiveObjectの中で探して、Global Object(window)までずっと.
メソッドの実行が完了すると、内部変数値はリセットされません.変数がいつ廃棄されるかは、次の項目を参照してください.
メソッド内の変数の生存周期は、アクティビティの参照が存在するかどうかによって異なります.
6と7は、クローズドを外部変数にアクセスできる根本的な原因です.
以上の内容は多くネットに転載して、個人のオリジナルではありません.