4

我很长时间没有使用 Javascript,今天一直在刷新自己。一直让我感动的一件事是this关键字。我知道在 jQuery 事件处理程序中,例如 click 事件,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 回调函数。jQuery 传递this的方式与我使用匿名回调函数所做的事情相似吗?我的this内部函数是指this我传入的吗?

我知道我可以这样做:

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

但我想弄清楚 jQuery 如何能够传递this给我的回调函数,即使我的函数需要 0 个参数。

4

4 回答 4

3

要回答您最后一个问题,您可以将您选择的接收器传递给 javascript 中的函数,例如调用

someFunction.call(someObject);

里面someFunctionthissomeObject

在你的情况下,你似乎想要的是

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

但是我们也可以使用方法 2,如果myFn它不是我们想要调用它的对象的属性,但是对象遵循正确的形式以便myFn能够对其进行操作(请参阅:duck typing):

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.callfn.apply两者都使用用于 的上下文参数来调用函数this

于 2012-09-26T19:16:34.673 回答
0

Applycallbind方法用于此目的。在您的情况下,您只需编写:

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