4

私は長い間 Javascript を使用していませんでしたが、今日は気分を一新しました。いつも私を惹きつけたのはthisキーワードでした。クリックイベントなどのjQueryイベントハンドラーでは、イベントを発生thisさせた要素を参照していることを知っています。this関数に引数がない場合でも、コールバックとして渡す関数にどのように渡されますか?

次のコードがあるとします。

$("tr.SummaryTbRow").data("Animating", false);
$("tr.SummaryTbAltRow").data("Animating", false);

$("tr.SummaryTbRow").click(function () {
    if ($(this).data("Animating") == false) {
        if ($(this).next(".Graph").css("display") == "none") {
            $(this).data("Animating", true);

            //Part I am questioning.
            setTimeout(function () {
                $(this).data("Animating", false);
            }(this), 550);

            $(this).next(".Graph").slideRow('down', 500);
        }
        else {
            $(this).data("Animating", true);
            $(this).next(".Graph").slideRow('up', 500);
        }
    }
});

SummaryTbRowクラスを持つ要素テーブル行を setTimeout コールバック関数に渡す方法を理解しようとしています。jQuerythisは、匿名のコールバック関数で行っていることと同様の方法で渡しますか? this関数内でthis渡された I を参照していますか?

私はただできることを知っています:

setTimeout(function (element) {
    $(element).data("Animating", false);
}(this), 550);

thisしかし、関数が引数を 0 とる場合でも、jQuery がコールバック関数にどのように渡すことができるかを理解したいと思います。

4

4 に答える 4

3

最後の質問に答えるために、たとえばcallを使用して、選択したレシーバーを JavaScript の関数に渡すことができます。

someFunction.call(someObject);

someFunctionthisになりますsomeObject

あなたの場合、あなたが望んでいるように見えるのは

setTimeout(function (element) {
    $(element).data("Animating", false);
}, 550, this); // this will be passed as element to the callback

または(より互換性があります

var _this = this;
setTimeout(function () {
    $(_this).data("Animating", false);
}, 550); 
于 2012-09-26T19:16:18.887 に答える
2

簡潔な答え:

this関数の.call()および.apply()メソッドを使用して、関数を設定できます。

長い答え:

任意の関数のthis変数は変数に似ていargumentsます (これはおそらくあなたが知らなかったものです)。関数が呼び出されたときに設定され、関数の呼び出し方法のアーティファクトです。説明するために、 のデモンストレーションから始めましょうarguments。検討:

myFunction = function () {
    return arguments.length;
};

次に、 へのいくつかの呼び出しを見てみましょうmyFunction

myFunction(); //is 0
myFunction(null); //is 1
myFunction(undefined); //is 1
myFunction(0, 0, 0, 0, 0); //is 5

ご覧のとおり、 の値はarguments.length、関数を記述した方法や場所に依存するのではなく、関数を呼び出した方法に依存します。同じことがthis変数にも当てはまります (「呼び出し元オブジェクト」とも呼ばれます)。呼び出し元のオブジェクトを設定するには、正確に 3 つの方法があります (ES5 には 4 番目の方法がありますが、無視します)。

  1. ドット表記を使用して関数を呼び出すことで設定できます(例something.myFunction()
  2. 関数の.call()または.apply()メソッドを使用して設定できます(例:myFunction.call(someObject)
  3. 方法 1 または 2 を使用して設定されていない場合は、デフォルトでグローバル オブジェクトになります (例: window) 。

したがって、ほとんどの人は方法 1 に慣れています。関数をオブジェクトのプロパティとして割り当て、オブジェクトとドット表記を使用して関数を呼び出すと、オブジェクトは として設定されthisます。そのようです:

var myFn = (function () { return this.x });

var myObj = {
    x: 1,
    y: myFn
};

myObj.myFn(); //is 1

myFnしかし、それを呼び出したいオブジェクトのプロパティではないが、オブジェクトがそれを操作できるように正しい形式に従っている場合は、メソッド 2 を使用することもできmyFnます (ダックタイピングを参照)。

var myOtherObj = {
    x: 2
}

myFn.call(myOtherObj); //is 2
myFn.apply(myOtherObj); //is 2
myFn.apply({ x : 3}); //is 3

かっこいいでしょ?これがjQueryのやり方です。コールバックを実行するときは、 (イベントのターゲット オブジェクトへの.apply(event.target)設定) を使用して実行します。this彼らはcallbacksフレームワークのためにより複雑な方法でそれを行いますが、アイデアはそこにあります.

とにかく、3 番目の方法について説明しなければ、長い答えを提供することはできません。

すべてのグローバル変数はグローバル オブジェクトの暗黙的なプロパティであるため、方法 3 からいくつかの興味深い効果が得られます。そのような:

var x = 4;
myFn(); //is 4

しかし、ほとんどの場合、呼び出し元のオブジェクトに対する関数の要件をグローバル オブジェクトが満たすほど幸運ではないため、通常はエラーが発生し、多くのフラストレーションが発生します。

おそらくあなたが探していた以上のものですが、呼び出し元のオブジェクトとその巧妙な方法について、より多くの情報が得られたことを願っています。

于 2012-09-26T19:16:45.423 に答える
1

に使用されるコンテキスト引数を使用して、fn.callまたはその両方を使用して関数を呼び出すことができます。fn.applythis

于 2012-09-26T19:16:34.673 に答える
0

Applycall 、およびbindメソッドがその目的に役立ちます。あなたの場合、次のように書くだけです:

setTimeout(function() {
  $(this).data("Animating", false);
}.bind(this), 550);
于 2012-09-26T19:18:42.903 に答える