对javascript中的'this'关键字感到困惑

时间:2012-09-26 19:14:26

标签: javascript jquery this

我很久没有使用过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 个答案:

答案 0 :(得分:3)

要回答你的上一个问题,你可以使用例如call将你选择的接收者传递给javascript函数:

someFunction.call(someObject);

someFunction内,this将是someObject

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

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

或(more compatible

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

答案 1 :(得分: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中有一种排序,但我们会忽略它):

  1. 您可以使用点符号(例如something.myFunction()
  2. 调用该函数来设置它
  3. 您可以使用函数的.call().apply()方法设置它(例如myFunction.call(someObject)
  4. 如果未使用方法#1或#2设置,则默认为全局对象(例如window
  5. 所以大多数人都习惯了方法#1。如果将函数指定为对象的属性,则使用object和dot-notation调用函数,然后将对象设置为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框架but the idea is there,他们以更复杂的方式执行此操作。

    无论如何,如果我没有对方法#3进行解释,我就不会提供一个很长的答案,这会让一些人完全疯狂:如果你没有设置调用对象会发生什么?

    因为所有全局变量都是全局对象的隐式属性,所以您可以从方法#3获得一些有趣的效果。如:

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

    但是大多数时候你没有足够的幸运能让你的全局对象满足函数对其调用对象的要求,所以通常它只会导致错误和很多挫折。

    可能比你想要的更多,但希望你现在对调用对象及其狡猾的方式更加了解。

答案 2 :(得分:1)

您可以使用fn.callfn.apply来调用函数,这两个函数都使用用于this的上下文参数。

答案 3 :(得分:0)

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

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