javascript中this対象の翼をください

7208 ワード

javascript関数の中のthisオブジェクトは他の言語と比べてかなり違っています.厳格モードと非厳格モードでも違います.
ほとんどの場合、thisオブジェクトは関数の呼び出しオブジェクトで決定されます.タスク実行中に、thisオブジェクトは変更できません.ECMAScript 5は、コール中のthisオブジェクトを設定するためにbindメソッドを導入しました.実際にはコンテキストを伝達し、次の時間があれば、bindメソッドを具体的に検討してもいいです.多くのフレームはすでに実現されています.
これらのたいへん空洞なので,いくつかの例を使ってみましょう.
function fn(){

    return this;

}



alert(fn() === window);  //true
この例では、結果と原因は明らかであり、fn()はグローバルオブジェクトwindowの呼び出しに相当し、window.fn()に相当するので、thisオブジェクトはwindowオブジェクトを指す.
var x = 0;

function fn(){

    alert(this.x);

}

var obj = {

    x: 1,

    f: fn,

}

obj.f();  //1
この例では、objオブジェクトのf属性はfn関数体を指すので、最後のobj.f()呼び出しは、オブジェクトobjが関数を呼び出しているので、ルールを適用して、this.xが1を表示します.
var x = 0;

function test(){

    return function(){

        console.log(this.x);

    };

}

var o = {x:1};

o.f = test;

o.f()();  //0
この例を見て、最終的に結果が0と表示されるのはなぜですか?分かりやすい点では、オブジェクトoの属性fはtest関数の参照であり、o.f()が得られた結果は、function(){consoline.logs(this.x)}であり、単独でこの関数を実行すると、thisオブジェクトはもちろんグローバルオブジェクトwindowに向けられ、結果は0である.ここでは、thisオブジェクトを簡単に理解して、複雑な例を見ないでください.覚えてください.変化してもその宗派から離れず、thisオブジェクトはその自身の関数を呼び出す対象を指します.
また、変数を使用してthisオブジェクトを保存し、コンテキストを変更することができます.コリック化の関数結合は典型的な伝達文脈技術である.ここでは多く話しません.今度は関数と結びつけて話しましょう.
最後にまとめて、thisの処理メカニズムは5つの異なる状況に分けられます.
①、全体の範囲は、グローバルオブジェクトを指します.
②、関数は直接呼び出して、同様にグローバルオブジェクトを指します.例えば、Fnc();   -- ES 5厳密モードでは、グローバル変数が存在しないため、undefinedとなります.
③方法コールは、呼び出し方法のオブジェクト、例えば、fn.func()を指します.thisはfnオブジェクトを指します.
④、コンストラクタを呼び出します.例えば、new func();ここでthisは新しく作成したオブジェクトを指します.
⑤文脈を伝える、例えば、apply(context、args)またはcall(context、arg 1、arg 2…)、thisはcontextを指す.
特に誤解しやすいところがあります.内部関数とは、次のように、もう一つの関数の中にあると宣言する関数です.
Fn.method = function() {

    function func() {

        // this           

    }

    func();

}
多くの初心者は誤解しやすいです.コードの中のthisはFnオブジェクトを指します.実はwindow全体のオブジェクトを指します.もしFnオブジェクトを使うなら、methodメソッド内に変数を作成してFnオブジェクトを引用します.通常は、開発者はthatまたはselfを使って交替します.
Fn.method = function() {

    var self= this;

    function func() {

        //    self    Fn   

    }

    func();

}
以上の説明を通して、thisの対象の働きの仕組みがよく理解されていると思います.要点を全部把握していると感じたら、それをもとにして適切に展開してもいいです.ここでまだ雲間にあるなら、詳しくこの文章を読むことをオススメします.
関数の実行コンテキスト(context)
関数が呼び出されたり、直接実行されたりすると、実行コンテキストが作成されます.関数のすべての挙動はここで実行されます.実行コンテキストを構築するには、javascriptはまず、関数を呼び出すときに入ってくるパラメータセットを含むargments変数を作成します.次に、スコープchainを作成します.を選択して、変数を初期化します.関数のイメージパラメータを含みます.関数の内部に関数がある場合は、これらの内部関数を初期化します.内部関数がない場合は、ローカル変数をundefinedに初期化し続けます.本当に値付け操作はコンテキスト作成が完了した後、関数実行時に値が割り当てられます.最後にthisオブジェクトに値を割り当てます.
コンテキストの作成が完了すると、関数はラインごとに実行されます.必要な変数は既に構築されている実行コンテキストから読み取ります.これもコンテキストを作成する目的と意味の一つです.
関数バインディング
他のオブジェクトの知識拡張点を変更することができます.関数バインディングとは、特定のコンテキストでパラメータを指定して別の関数を呼び出す関数のことです.この技法は、変数として関数を伝達しながら、コードのコンテキストを保持するために、コールバック関数とイベントハンドラと一緒によく使われます.
var x = 9; 

var obj= {

  x: 81,

  getX: function(y) {console.log('x: ' + this.x + ', y: ' + y);}

};

obj.getX(); //   x: 81, y: undefined

var fn = obj.getX;

fn();  //   x: 9, y: undefined
上記の結果の原因はご存知のように、fn()実行時は、Objコンテキストを保存していませんが、実際には大域的なコンテキストで実行されていますので、結果は9です.しかし、関数バインディング技術を通じて、コンテキスト変更の結果を伝えて、私たちの予想に達することができます.
function bind(func, context){

    var args = Array.prototype.slice.call(arguments, 2);  //    ,args   ,  bind(obj.getX, obj),         

    return function(){

        var innerArgs = Array.prototype.slice.call(arguments);  //fn(88)innerArgs 88,fn()  

        var finalArgs = args.concat(innerArgs);

        return func.apply(context, finalArgs);

    };

}

var fn = bind(obj.getX, obj);  //         

fn();    //   x: 81, y: undefined

fn(88);  //   x: 81, y: 88
bind関数は、2つのテクニックを使用しています.①、関数バインディング、②、パラメータコリック化.bind関数は、2つのパラメータを伝達しています.1つは、呼び出された関数で、1つは期待されたコンテキストです.次に、関数体はどのようなことをしましたか?全体的には、bind関数は、クローズドされています.また、戻る関数の中で外部の変数argsにアクセスしました.変数argsは、bind関数を保存して転送された参加集合であり、3番目のビットから取得し、func、contextの実際のパラメータ値を削除します.戻る関数の体内では、innerArgsは戻り関数の実際のパラメータを保存するために使用されます.例のfn()です.のパラメータを入力します.次に、argsパラメータと呼び出されたinnerargsを新しい配列につづり合わせて、最後にFncがcontextコンテキストで実行された結果を返します.
バインディング関数は強力な動的関数作成機能を提供することができますが、濫用することはできません.すべての関数は追加のオーバーヘッドをもたらします.