简体   繁体   English

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

[英]Confused about the 'this' keyword in javascript

I haven't used Javascript in a long time and have been refreshing myself on it today. 我已经很久没有使用Javascript了,今天一直在刷新自己。 One thing that always got me was the this keyword. 总是让我着迷的一件事是this关键字。 I know in jQuery event handlers, such as the click event, this refers to the element that fired the event. 我知道在jQuery事件处理程序(例如click事件)中, this是指触发事件的元素。 How is this passed to the function that I give it as a callback even though my function has no arguments? 即使我的函数没有参数, this如何传递给作为回调的函数?

Given the following code: 给出以下代码:

$("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);
        }
    }
});

I am trying to figure out how to pass the element table row with class SummaryTbRow to my setTimeout call back function. 我试图弄清楚如何将带有类SummaryTbRow的元素表行SummaryTbRow给我的setTimeout回调函数。 Does jQuery pass this in a similar fasion to what I am doing with my anonymous call back function? jQuery是否以类似于我使用匿名回调函数的方式传递了this Does my this inside the function refer to the this I pass in? 我的函数内的this是否指代我传入的this

I know I could just do: 我知道我可以做:

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

But I want to figure out how jQuery is able to pass this to my call back function even though my function takes 0 arguments. 但是,我想弄清楚的jQuery是如何能够通过this我的回调函数,即使我的函数接受0参数。

To answer you last question, you may pass the receiver of your choice to a function in javascript using for exemple call : 为了回答您的最后一个问题,您可以将您选择的接收者传递给javascript中的函数,用于示例调用

someFunction.call(someObject);

Inside someFunction , this will be someObject . someFunction内部, this将是someObject

In your case, what you seem to want is 就您而言,您似乎想要的是

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

or ( more compatible ) 或( 更兼容

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

Short answer: 简短答案:

You can set this on a function by using the function's .call() and .apply() methods. 您可以设置this使用功能的上的功能.call().apply()方法。

Long answer: 长答案:

The this variable on any function is similar to the arguments variable (which is probably something you didn't know about). 任何函数上的this变量都类似于arguments变量(这可能是您所不知道的)。 It's set when the function is called and is an artifact of how the function is called. 它是在调用函数时设置的,它是函数调用方式的构件。 To explain, let me start with a demonstration of arguments . 为了解释,让我从arguments Consider: 考虑:

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

Now let's look at a couple calls to myFunction : 现在,让我们看一下对myFunction的几个调用:

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

As you can see, the value of arguments.length is not dependent on how or where we wrote the function, but on how we called the function. 正如你所看到的,价值arguments.length不依赖于如何或在哪里我们写的功能,但我们如何调用该函数。 The same is true of the this variable (otherwise known as the "calling object"). this变量(也称为“调用对象”)也是如此。 There are exactly 3 methods for setting the calling object (there's a sort-of 4th in ES5, but we'll ignore that): 设置调用对象的方法恰好有3种(ES5中大约有4种,但我们将忽略它):

  1. You can set it by calling the function using dot-notation (eg something.myFunction() ) 您可以通过使用点符号调用函数来设置它(例如, something.myFunction()
  2. You can set it by using the function's .call() or .apply() methods (eg myFunction.call(someObject) ) 您可以通过使用该功能的设置.call().apply()方法(如myFunction.call(someObject)
  3. If it's not set using method #1 or #2, it will default to the global object (eg window ) 如果未使用方法1或方法2进行设置,则默认使用全局对象(例如window

So most people are used to method #1. 因此,大多数人习惯于方法1。 If you assign your function as a property of an object, then call the function using the object and dot-notation, then the object gets set as this . 如果将函数分配为对象的属性,然后使用对象和点符号调用函数,则对象将设置为this Like so: 像这样:

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

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

myObj.myFn(); //is 1

But we can also use method 2 if myFn isn't a property of the object we want to call it on but the object follows the correct form for myFn to be able to act on it (see: duck typing): 但是,如果myFn不是我们要调用的对象的属性,但是该对象遵循正确的形式使myFn可以对其执行操作,则我们也可以使用方法2(请参阅:鸭子键入):

var myOtherObj = {
    x: 2
}

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

Pretty cool, eh? 很酷吧? This is how jQuery does it. jQuery就是这样做的。 When they execute your callback, they do so using .apply(event.target) (setting this to the event's target object). 当他们执行回调函数,他们这样做用.apply(event.target)设置this到事件的目标对象)。 They do it in a more complex manner because of their callbacks framework, but the idea is there . 由于使用了callbacks框架,因此它们以更复杂的方式进行操作, 但是这个想法就存在了

Anyway, I wouldn't be offering a long answer if I didn't toss in an explanation of method #3, which drives some people totally insane: What happens if you don't set the calling object? 无论如何,如果我不扔方法3的解释,那我就不会给出很长的答案,这使一些人完全发疯:如果不设置调用对象会发生什么?

Because all global variables are implicit properties of the global object, you get some interesting effects from method #3. 因为所有全局变量都是全局对象的隐式属性,所以您可以从方法3中获得一些有趣的效果。 Such as: 如:

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

But most of the time you're not lucky enough to have your global object meet the requirements the function has for its calling object, so usually it just results in an error and a lot of frustration. 但是大多数时候,您不是很幸运地使您的全局对象满足函数对其调用对象的要求,因此通常只会导致错误和很多挫败感。

Probably more than you were looking for, but hopefully you're now much more informed on the calling object and its wily ways. 可能比您期望的要多,但希望您现在对调用对象及其巧妙的方式有了更多的了解。

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

Apply , call and bind methods serve for that purpose. Applycallbind方法用于此目的。 In your case you just write: 就您而言,您只需编写:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM