Confused about the 'this' keyword in javascript

Refresh

November 2018

Views

186 time

4

I haven't used Javascript in a long time and have been refreshing myself on it today. One thing that always got me was the this keyword. I know in jQuery event handlers, such as the click event, this refers to the element that fired the event. How is this passed to the function that I give it as a callback even though my function has no arguments?

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. Does jQuery pass this in a similar fasion to what I am doing with my anonymous call back function? Does my this inside the function refer to the this I pass in?

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.

4 answers

1

Вы можете вызвать функцию , используя fn.callили fn.applyоба из которых принимать контекст аргумент , который используется для this.

3

Для того, чтобы ответить вам последний вопрос, вы можете передать получателю вашего выбора функции в JavaScript , используя для Exemple вызова :

someFunction.call(someObject);

Внутри someFunction, thisбудет 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); 
0

Применить , звоните и связывают методы служат для этой цели. В вашем случае вы просто пишете:

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

Short answer:

You can set this on a function by using the function's .call() and .apply() methods.

Long answer:

The this variable on any function is similar to the arguments variable (which is probably something you didn't know about). 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. Consider:

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

Now let's look at a couple calls to myFunction:

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

Как вы можете видеть, значение arguments.lengthне зависит от того, как и где мы написали функцию, но о том , как мы называли функцию. То же самое относится и к thisпеременной (иначе известный как «вызывающий объект»). Есть ровно 3 способа настройки объекта вызова (есть своего рода-4 - го в ES5, но мы будем игнорировать это):

  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чтобы иметь возможность воздействовать на него (см утиной типизации):

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

Но большую часть времени вы не достаточно удачлив, чтобы иметь свой глобальный объект отвечает требованиям функция имеет для ее вызывающего объекта, поэтому обычно это просто приводит к ошибке и много разочарований.

Наверное, больше, чем вы искали, но, надеюсь, вы теперь гораздо более информированы о вызывающем объекте и его коварных способах.