2015-05-08 3 views
0

У меня две огромные проблемы с областью this в моем javascript-коде. После создания объекта setAJAXGet функция обратного вызова была потеряна и не может быть вызвана правильно. Поэтому вместо вызова this.funct я установил ajax.parent = this; и звоните this.parent.funct - работает нормально.Двойная проблема с «этой» областью в xmlhttprequest javascript

function setAJAXGet() { 
    this.askServer = function() { 
    var ajax = new XMLHttpRequest(); 
    ajax.parent = this; 
    ajax.contentType = "charset:utf-8"; 
    ajax.onreadystatechange = function() { 
      if (ajax.readyState==4 && ajax.status==200) { 
      this.parent.funct(ajax.responseText); 
      } 
    } 
    ajax.open("GET", this.url+'?'+this.vars, true); 
    ajax.setRequestHeader("Content-Type", "text/xml; charset=utf-8"); 
    if (navigator.onLine) ajax.send(null); else this.functError(); 
    } 
this.functError; 
this.funct; 
this.vars; 
this.url; 
} 

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

function someObject() { 
    this.asyncGet = function() { 
    var get = new setAJAXGet(); 
    //do some config here... 
    get.funct = this.processAsyncData; 
    get.askServer(); 
    } 

    this.someOtherFunction = function() { 
    } 

    this.processAsyncData = function(ajaxText) { 
    // ajaxText is OK 
    this.someOtherFunction(); 
    // this.someOtherFunction is not defined (how so?) 
    } 

this.asyncGet(); 
} 

я могу решить эту проблему путем передачи объекта к processAsyncData модифицированным setAJAXGet() в качестве аргумента, но это выглядит некрасиво.

function someObject() { 
    this.asyncGet = function() { 
    var get = new modifiedSetAJAXGet(); 
    //do config here... 
    get.object = this; // stores 'this' and sends it to callback as argument 
    get.funct = this.processAsyncData; 
    get.askServer(); 
    } 

    this.someOtherFunction = function() { 
    } 

    this.processAsyncData = function(object, ajaxText) { 
    // ajaxText is OK 
    object.someOtherFunction(); 
    // object.someOtherFunction works just fine 
    } 

this.asyncGet(); 
} 

Я считаю, что вы знаете более элегантное решение.

+2

Я предлагаю вам прочитать этот праймер о том, как установлено значение 'this': http://stackoverflow.com/questions/28016664/when-you-pass-this-as-an-argument/28016676# 28016676 – jfriend00

+0

Почему бы не классический 'var self = this' в верхней части вашей функции? – Mathletics

+0

@Mathletics где я должен положить 'var self = this'? –

ответ

0

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

Когда вы делаете что-то вроде этого:

get.funct = this.processAsyncData; 

То, что можно положить в get.funct указатель на метод processAsyncData. Совсем нет связи с this значением в get.funct. Итак, когда-нибудь позже вы вызовете get.funct(), это будет не то же самое, что вызывать this. processAsyncData(). Значение this будет потеряно.

Здесь .bind() пригодится. Вы можете прочитать о .bind here. То, что он делает, это создать временную заглушку для функции, которая привязывает ваше значение this, так что вышеуказанное разделение не произойдет. Таким образом, вы могли бы использовать его как это:

get.funct = this.processAsyncData.bind(this); 

Затем, когда вы звоните get.funct(), он будет генерировать точно такой же вызов функции и значение this как this.processAsyncData() бы потому, что .bind() создал функцию заглушки автоматически повторно присоедините желаемое значение this.

Как я опубликовал в более раннем комментарии, есть очень хорошее резюме того, как значение this контролируется в этом другом ответе: When you pass 'this' as an argument.

Примечание. Мое предложенное решение отличается от того, о котором вы упомянули в своем комментарии. Я предполагаю, что вы исправляете проблему ранее в этом процессе, поэтому метод .funct может быть вызван любым пользователем в любое время без необходимости делать что-то особенное.

Смежные вопросы