詳しく読んでください.「あなたの知らないJavaScript・上巻」1-2品詞の作用領域

5533 ワード

墨の妹はあなたを連れて《あなたの知らないJavaScript》シリーズの世界を詳しく読んで、JavaScript言語の内部に深く入り込んで、JavaScriptのすべての部品の用途をはっきりさせて、それが更にその理由を知っています.
読み解く
1章では、エンジンが現在のスコープおよびネストされたサブスコープにおいて、識別子名に従って変数検索を行う方法を管理するための規則であるスコープを学習した.
作用域には2つの主要な工作モデルがあり、一つは語法の作用域(JavaScriptなど)である.第二に、ダイナミックスコープ(bashシナリオなど)である.
語法のスコープ
  • 何が品詞作用領域ですか?
  • 、なぜ詐欺詞の作用領域を廃棄したかという二つのメカニズム
  • .
    2.1品詞の段階
    第1章で勉強しました.ほとんどの標準言語コンパイラの最初の作業段階は語法化です.
    語法の作用域とは、語法分析の際に定義される作用域であり、コードを書く際に変数とブロックの作用領域の位置によって決定されます.したがって、語法分析の際にも固定的に変化しています.
    以下の例のコードには三つのネストされたスコープがあります.
  • 丸1は、グローバルスコープを含み、1つの識別記号token
  • のみが存在する.
  • 丸2はfoo作用領域を含み、3つの識別子fooabar
  • がある.
  • 輪3はb作用領域を含み、識別子bar
  • がある.
    スコープの範囲は、スコープコードブロックによって定義された位置によって決定され、ここでは、各関数が一つのスコープを作成する.
    ここでのスコープのネストは厳密であり、一つの関数は二つの外部関数の中に同時に存在してはいけない.
    2.1.1検索
  • スコープ探索は、最初の一致する識別子を見つけると停止される.
  • マスク効果:多層ネストされたスコープには同名の識別子が定義され、内部の識別子は外部の識別子を覆い隠す.
  • グローバル変数はグローバルオブジェクトの属性で、上書きされた非グローバルオブジェクトはアクセスできません.
    window.a
    
  • 語法のスコープ検索は、cabcなどの一級の識別子だけを検索します.コードにfoo.bar.bazを参照した場合、スコープはfoo識別子だけを検索します.見つかったら、対象属性アクセス規則はそれぞれbarおよびbaz属性へのアクセスを受けます.
  • 2.2だましの語法
    誤魔化しの語法は機能が低下するため、以下の2つの方法が推奨されていません.
    2.2.1 eval
  • eval(...)関数は、1つの文字列をパラメータとして受け入れ、文字列の内容をコードとして実行し、語法作用領域環境の変更を実現することができる.
  • eval()を実行した後のコードは、エンジンが知らないし、前のコードが動的コンパイルされていることにも関心を持たないし、語法作用ドメイン環境が修正されました.エンジンはいつものようにワードスコープ検索を行います.
    非厳格モードで:
    function foo(a, str){
            console.log(str);           //2       // var b = 3;
    	eval(str); //   !
    	console.log(eval(str));     //2      //undefined
    	console.log(a, b);          //0   2  // 1  3
    	console.log(a, window.b);   //0   2  //1  2
    }
    var b = 2;
    foo(0, b);
    foo(1, " var b = 3 ;"); 
    
  • eval()が呼び出されたとき、文字列パラメータ“ var b = 3; ”は、変数bを真正のコードとして宣言し、foo()の品詞作用領域を修正しました.foo()の内部に、一つの変数b ,が外部の大域作用領域における同名変数bを遮蔽しました.
  • console.log()が実行されると、foo()の内部にabが発見されますが、外部のbが永遠に見つからないため、通常の場合に出力される1 , 3ではなく1 ,2が出力されます.eval()関数を拡張し、undefiendの知識を理解するには、以下をクリックしてください.
    MDN解析eval()判例
    js中のeval方法詳細解(一)
    eval()関数の使用
    厳しいモードで:
    function foo(a, str){
        "use strict";
         console.log(str);           //2       // var b = 3;
         eval(str); 
         console.log(eval(str));    //2       //undefined
         console.log(a, b);         //0  2    // 1  2
         console.log(a, window.b);  //0  2    //1  2
    }
    var b = 2;
    foo(0, b);
    foo(1, " var b = 3 ;");
    
  • eval()は、厳格なモードにおいて、自分の語彙作用領域があり、その中の声明は、スコープを修正することができない.
  • setTimeout(...)およびsetInterval(...)の最初のパラメータは文字列であってもよく、文字列の内容は動的に生成された関数コードとして解釈されます.使用は破棄されました.
  • コンストラクションnew Function()の最後のパラメータはコード文字列(前のパラメータは新しく生成された関数のイメージ)を受け入れて使用を避けることができます.
    2.2.2 withwithは、通常、同じオブジェクトの複数の属性を繰り返し参照するショートカットとして扱われ、参照オブジェクト自体を重複させなくてもよい.
    var obj = {
    	a:1,
    	b:2,
    	c:3
    };
    
    //       “ obj ”
    obj.a = 2;
    obj.b = 3;
    obj.c = 4;
    
    //       
    with(obj){
    	a = 3;
    	b = 4;
    	c = 5;
    }
    
    属性だけでなく、アクセスのショートカットは以下の通りです.
    function foo(obj){
    	with(obj){
    		a = 2;
    	}
    }
    
    var o1 = {
    	a : 3
    };
    
    var o2 = {
    	b : 4
    };
    
    console.log(o1.a);//3
    foo(o1);
    console.log(o1.a);//2
    
    foo(o2);
    console.log(02.a);//undefined
    console.log(a);//2 ->   ,a            !
    
  • o1が転送された後、withが宣言したロールドメインはo1であり、a = 2が割り当てられたオペレーションはo1.aを見つけ、2をそれに割り当てた.
  • o2が転送された後、スコープo2a属性がないとLHS識別子のルックアップが行われ、o2のスコープ、foo()のスコープ、およびグローバルスコープは識別子aが見つからないので、a = 2が実行されると、副作用が発生し、自動的にグローバル変数が作成されます.aは、2aに与えているので、o2.aundefinedを保持している.
  • 厳密なモードでは、with文は完全に無効にされています.eval()はコア機能だけを保持しています.
    2.2.3性能JavaScriptエンジンはコンパイル段階で様々な性能最適化を行い、いくつかの最適化は語法分析段階でコードを静的に分析し、予め変数と関数宣言の位置を決定しているので、実行中に迅速に識別子を解析することができる.
    2.3まとめ
    語法のスコープは関数が宣言された時の位置だけで決定されます.
    以下の2つの機構は、語法のスコープを欺くことができる.
  • eval(...):1つ以上の声明を含むセグメントのコード文字列を演算し、既存の動作領域を修正します.
  • with:オブジェクトの参照を作用領域とし、オブジェクトの属性を作用領域の識別子として、新しい語法作用領域を作成する(実行時).
    副作用はエンジンがコンパイル時に機能領域の検索を最適化できないことです.エンジンはこのような最適化が無効であると慎重にしか考えられません.どのメカニズムを使ってもコードの運行が遅くなります.それらを廃棄します.
    最後に、本を読むのは厚いから薄いまでで、また薄いから厚いまでの双方向の過程で、悟り、実践を重視して、絶えずピットを踏んで、昇格させます.
    参考文献:
    木易楊のブログ
    ブログです
    taoppyブログ
    履歴記事:
    詳しく読んでください.「知らないJavaScript・上巻」1-1のスコープは何ですか?
    【訳】30 Seconds of ES 6(一)