Javascriptのオブジェクト検索


最近の群の中には簡単な問題を提出する人がいます.例えば、コードがめちゃくちゃなコードを送って、中の変数は何ですか?例えば、ここでいい例があります.
    
    
    
    
function fn(arg) {
alert(
this .arg);
alert(
this );
}
fn(
123 );
var o = { fn: fn };
o.fn(
123 );
そして、このような問題があります.
なぜthis.argはundefinedですか?なぜ2回の呼出fnのthisは違いますか?
そのためには、未熟ながらも自分のできることについて、伝道して教えていくべきだと思います.だから、この文章は非常に浅い面から、javascriptの対象検索がどのように行われているか説明するつもりです.
注意してください.この文章は対象を表象から紹介して検索する過程だけで、文章の中の観点は全部正しいとは言えないです.誤謬もありますが、これも初心者に対象をよりよく理解させるために検索する過程です.抽象的で深みのある話をすると、かえってマイナス効果を引き起こしてしまうと信じています.もしある日、あなたが戻ってきたら、この文章は正しくないと分かりました.おめでとうございます.その時のあなたは正しい道を見つけられました.この中の間違いはもうあなたに影響を与えません.
オブジェクトの分類
オブジェクト検索とは、実行可能なコードの範囲内で、現在必要なオブジェクトを見つけます.javascriptでは、検索する対象は大きく3つのタイプに分けられます.
  • 変数検索、foo++;など、ここでfooという変数を検索します.
  • 属性検索は、foo.bar++;など、fooという変数の次のbarという属性を検索します.
  • this検索は、thisキーワードに対する処理である.
  • この3つのタイプを区別する対象の検索は、まず達成すべき課題であり、以下の原則に基づいて判断できます.
  • 変数は、変数名だけで構成されています.すなわち、単独のfoo、barなどです.
  • 属性は、常に2つの形式でアクセスされる.すなわちfoo.barfoo['bar']である.したがって、「.」または「[]」があると、属性検索として扱うことができる.
  • thisはもちろん、良いキーワードです.
  • このコードを見てください.
        
        
        
        
    var foo = this ;
    foo.bar();
    この2行のコードは3つのオブジェクトの検索を表しています.それぞれ:
  • は、thisオブジェクトを検索し、foo変数に値を与えます.
  • はfoo変数を調べます.
  • は、foo変数のbar属性を検索し、これを関数として呼び出します.
  • 変数の検索
    オブジェクトの検索が変数検索として決定されると、変数検索の規則に従って参照できます.
    変数の検索、すなわち作用ドメインチェーンを検索します.作用ドメインチェーンはjavascriptの非常に有名な2つのチェーンの一つです.以下のコードは標準的な作用ドメインチェーンを表しています.
        
        
        
        
    var foo = 1 ;
    function a() {
    var bar = 2 ;
    function b() {
    foo
    = 3 ;
    function c() {
    alert(foo
    + ' , ' + bar); //
    }
    c();
    }
    b();
    }
    a();
    c関数では、2つの変数を調べ、それぞれfooとbarです.
    変数の検索は、「下から上へ」という原則を簡単に守ることができます.
  • は関数cの範囲内でfooとbarを検索しました.明らかにcにはfooとbarの声明がありません.検索に失敗しました.
  • は、cの関数、すなわち関数bを含む範囲でfooとbarを検索します.bの中にはfooに対する割当値だけがあり、検索に失敗しました.
  • は、bを含む関数、すなわち関数aの範囲内でfooとbarを検索し、barの声明を見つけることができるので、barは2であると判断する.
  • aはいかなる関数にも含まれていないので、グローバルスコープ内でfooを検索し、fooの宣言があることが分かり、fooの値は1であると判定される.しかし、関数bでは、このfooに対して割り当てがあるので、fooの値は3に変更されます.
  • において、fooの値は3、barの値は2であると判断されたので、"3,2"が出力される.
  • まとめてみますと、変数の検索は、是延がスコープを使って行われ、スコープは簡単に関数間の包含関係と見なされ、含まれる関数に変数が存在しない場合、グローバルスコープまで彼の関数を含めて検索されます.
    属性の検索
    オブジェクトの検索が属性検索として決定されると、属性検索の規則に従って表示されます.
    属性の検索、すなわちプロトタイプチェーンを検索します.プロトタイプチェーンはjavascriptチェーンのもう一つのチェーンです.以下はプロトタイプチェーンを表します.
        
        
        
        
    var a = function () {};
    var b = function () {};
    var c = function () {};
    b.prototype
    = new a();
    c.prototype
    = new b();
    a.prototype.foo
    = 1 ;
    b.prototype.bar
    = 2 ;
    c.prototype.foo
    = 3 ;
    var o = new c();
    alert(o.foo
    + ' , ' + o.bar); //
    属性検索はプロトタイプを探し続けるプロセスです.
  • 検索c.prototypeには、fooとbarを定義する表示がありますか?fooが定義されています.その値は3です.
  • c.prototypenew b()によって得られたオブジェクトであることを発見しました.b.prototypeを検索すると、定義barが表示されていますか?定義されています.その値は2です.
  • は、fooの値が3であると判断し、barの値が2で"3,2"を出力する.
  • まとめてみます.属性検索は是延のプロトタイプチェーンで行われています.プロトタイプチェーンの具体的な知識はここでは詳しく説明しません.別の文章を探して参考にしてもいいです.すべてのオブジェクトのプロトタイプチェーンは最終的にObject.prototypeになります.
    thisの検索
    thisの検索は多くの人が迷っています.this不安定という見方を持っている人も多いようです.本当に言葉がありません.thisの検索は、3つのオブジェクトの検索の中で最も簡単であると言えます.実は、thisオブジェクトの決定には、「検索」のプロセスがありません.
    まず、thisオブジェクトは一つの関数の中でしか確定できません.もし全ローカルエリアであれば、thisは永遠にGlobalオブジェクトです.ブラウザでは通常windowオブジェクトです.javascriptでは関数の呼び出しは全部で4つの方式があります.
    Function Invocation Pattern
    `foo()のような呼び出しの形をFunction Invocation Patternと呼び、関数の最も直接的な使用形態であり、ここでのfooは属性ではなく独自の変数として出現することに注意してください.
    このモードでは、foo関数体のthisは常にGlobalオブジェクトであり、ブラウザではwindowオブジェクトである.
    Method Invocation Pattern
    `foo.bar()`のような呼び出し形式はMethod Invocation Patternと呼ばれていますが、呼び出された関数がオブジェクトの属性として現れるのが特徴ですので、必ず「.」や「[]」というキー記号があります.
    このようなモードでは、バー関数体のthisは永遠に「.」または「[]前のオブジェクトであり、上記の例では必ずfooオブジェクトである.
    Costructor Pattern
    `new foo()`このような形式の呼び出しはCostructor Patternと呼ばれ、そのキーワード`new`は問題を説明しやすく、識別しやすいです.
    このモードでは、foo関数内部のthisは、常にnew foo()が返すオブジェクトである.
    Apple Pattern
    `foo.call`と`foo.appley`の形をApple Patternといい、内蔵の`call`と`appy`関数を使っています.
    このモードでは、`call`と`apply`の最初のパラメータがfoo関数内のthisであり、thisObjectが`null`または`undefined`であれば、Globalオブジェクトになります.
    以上の4つの方法を適用して、関数がどのようなPatternを使って呼び出されているかを確認すると、thisとは何かを確認しやすくなります.
    また、thisは、ドメインチェーンやプロトタイプチェーンに「検索」のプロセスが現れることは永遠にありません.関数呼び出し時には完全に確認されます.
    締め括りをつける
    オブジェクトの検索:
  • は、変数検索、属性検索、またはthis検索であると判断した.
  • 変数の検索であれば、ドメインチェーンが見つかりません.ReferenceErrです.
  • 属性検索なら、プロトタイプチェーンを延長して探します.歪を探すならundefinedです.
  • this検索であれば、呼び出し関数のコードを探して呼び出しの形でthisとは何かを決定します.
  • は、一度の検索プロセスを分割することに注意してください.例えばthis.foo.bar.yahoo()は、このようなコードに分割することができ、より明確になります.
          
          
          
          
    var o = this ; // this
    var foo = o. this ; //
    var bar = foo.bar; //
    bar.yahoo(); // , Method Invocation Pattern
  • 最後に、もしいつかこれらのことを知ることができれば、この文章はあなたのユーザーにとっても大きくないです.
  • どうして延在領域が調べられないのですか?
  • 実は変数も属性であり、特殊なオブジェクトの属性です.
  • thisはGlobalではないかもしれません.undefinedかもしれません.