JavaScript — ссылка на «это» во внутренней функции

Рассмотрим следующий код:

MyClass.prototype.my_func = function () {
    this.x = 10;
    $.ajax({
        // ...
        success: function (data) {
            alert(this.x);
        }
    });
}

Это не работает, поскольку, по-видимому, this не привязан к контексту выполнения замыкания. Я смог обойти это, введя другую переменную:

var _this = this;

И это работает внутри анонимной функции. Но выглядит довольно некрасиво для меня. Есть ли хороший способ справиться с этим?


person Andrey Balaguta    schedule 14.11.2011    source источник
comment
Я думаю, что предложенное вами решение -- var _this = this; -- является стандартным обходным путем.   -  person LukeH    schedule 14.11.2011
comment
Стандартный обходной путь использует вместо этого var that: P   -  person hugomg    schedule 14.11.2011
comment
@LukeH Я бы даже не назвал это обходным решением   -  person ZenMaster    schedule 14.11.2011


Ответы (4)


Это может показаться вам уродливым решением, и есть несколько обходных путей (например, используя метод bind() для изменения контекста), но это лучшее известное мне решение.

В качестве альтернативы вы можете изменить его на:

var self = this;

или дайте ему более осмысленное имя, но было бы лучше (в данном случае) не менять контекст, так как он может вам когда-нибудь понадобиться.

person Tadeck    schedule 14.11.2011

Вы можете использовать Function.prototype.bind для этого:

MyClass.prototype.my_func = function () {
    this.x = 10;
    $.ajax({
        // ...
        success: function (data) {
            alert(this.x);
        }.bind(this);
    });
}

Теперь переменная родительского контекста также привязана к анонимной функции.

person jAndy    schedule 14.11.2011
comment
@Энди: ну, это вполне возможно. .bind() является довольно новым из спецификаций ES5, поэтому он может не поддерживаться старыми браузерами. - person jAndy; 14.11.2011
comment
@Andy: В своем ответе я дал ссылку на статью MDN о bind() и о том, как реализовать ее в старых браузерах, так что вы можете увидеть это там. Но я все еще думаю, что это не тот путь, о котором я упоминал в своем ответе. - person Tadeck; 14.11.2011

синтаксис this обычно относится к объекту, а не к функции. В вашем случае this относится к MyClass.

Если вы используете переменную в объекте, вы, вероятно, забыли определить x в MyClass.

Если вы используете переменную ТОЛЬКО внутри функции, я бы определил свои переменные, используя синтаксис var. Переменные, определенные внутри функции, уничтожаются, когда функция завершается.

MyClass.prototype.my_func = function () {
    var x = 10;

    $.ajax({
        // ...
        success: function (data) {
            alert(x);
        }
    });
}
person Tim S.    schedule 14.11.2011

Закрытие будет иметь доступ ко всем объектам, определенным в контексте его родителя. Итак, если у нас есть:

function() {
  var x = 10;
}

Тогда это действительно:

function() {
  var x = 10;

  (function() {
    alert(2*x); // 20
  }())
}

Следовательно, когда вы определяете var _this = this, вы просто определяете новую переменную в родительском контексте, которая доступна в замыкании. См. вопрос № 4371333 для получения дополнительной информации об этом "шаблоне".

person James Sumners    schedule 14.11.2011