Почему это закрытие не имеет доступа к ключевому слову 'this'? - jQuery

Я начинаю закрывать (и Javscript вообще), и я не могу найти удовлетворительное объяснение того, что происходит в этом коде:

function myObject(){
    this.myHello = "hello";
    this.myMethod = do_stuff;
}

function do_stuff(){
    var myThis = this;
    $.get('http://example.com', function(){
        alert(this.myHello);
        alert(myThis.myHello);
    });
}

var obj = new myObject;
obj.myMethod();

Он будет предупреждать "undefined", а затем "привет". Очевидно, это не должно быть специфичным для jQuery, но это простейшая форма моего исходного кода, который я мог бы придумать. Закрытие в do_stuff() имеет доступ к переменным в этой области видимости, но, видимо, это правило не относится к ключевому слову this.

Вопросы:

Что происходит с this, когда закрытие выходит за пределы области do_stuff() (в данном случае $.get())? Имеет ли myThis копию this или ссылку на нее? Как правило, не рекомендуется использовать this в закрытии?

Любой ответ очень ценится.

Ответы

Ответ 1

Что происходит с этим, когда закрытие выходит за пределы do_stuff() (в этом случае $.get())?

Каждая функция имеет свой собственный контекст выполнения, ключевое слово this получает значение текущего контекста.

Идентификатор doStuff и свойство obj.myMethod относятся к одному и тому же функциональному объекту, но поскольку вы вызываете его как свойство объекта (obj.myMethod();), значение this внутри этой функции будет ссылаться до obj.

Когда запрос Ajax преуспел, jQuery вызовет вторую функцию (начиная новый контекст выполнения) и будет использовать объект, содержащий параметры, используемые для запроса, как значение this этого обратного вызова.

Имеет ли myThis копию этого или ссылки на него?

Идентификатор myThis будет содержать ссылку на объект, на который также ссылается значение this во внешней области.

Как правило, это не рекомендуется использовать в закрытии?

Если вы понимаете, как значение this обрабатывается неявно, я не вижу никаких проблем...

Поскольку вы используете jQuery, вам может понадобиться проверить метод jQuery.proxy, это полезный метод, который можно использовать для сохранения контекст функции, например:

function myObject(){
    this.myHello = "hello";
    this.myMethod = do_stuff;
}

function do_stuff(){
    $.get('http://example.com', jQuery.proxy(function(){
        alert(this.myHello);
    }, this)); // we are binding the outer this value as the this value inside
}

var obj = new myObject;
obj.myMethod();

См. также:

Ответ 2

$.get('http://example.com', function(){
    alert(this.myHello);  // this is scoped to the function
    alert(myThis.myHello);  // myThis is 'closed-in'; defined outside
});

Обратите внимание на анонимную функцию. это в этой области охвата функции. myThis - это внешний охват, где myHello определен. Проверьте это в firebug.

'this' всегда ссылается на текущую область исполнения, я считаю. Если вы хотите взять текущую область и сохранить ее, вы делаете то, что вы сделали, что присваивает ей другую переменную.

Ответ 3

$.get('http://example.com', function(){
   // inside jQuery ajax functions - this == the options used for the ajax call
});

Что происходит с этим, когда закрытие выходит за пределы do_stuff() (в этом случае $.get())?

Ничего "не происходит" с этим, это все еще это для этого закрытия, контекст выполнения функций, вызываемых из замыкания, не наследует автоматически this.

Есть ли в myThis копия этого или ссылки на него?

Все нескалярные назначения являются ссылками в JavaScript. Таким образом, это ссылка на this, если вы меняете свойства на обоих, они изменяются для обоих.

Как правило, это не рекомендуется использовать в закрытии?

Как правило, рекомендуется использовать this в закрытии, но если вы собираетесь использовать закрытие внутри, которым нужно получить доступ к тем же this, то его хорошая практика - сделать то, что вы сделали: var someName = this;, а затем используйте someName