2

эта вещь работает почти:Javascript класс вызова XMLHttpRequest внутри, то обработка onreadystatechange

function myClass(url) { 

this.source = url; 
this.rq = null; 
this.someOtherProperty = "hello"; 

// open connection to the ajax server 
this.start = function() { 
    if (window.XMLHttpRequest) { 
     this.rq = new XMLHttpRequest(); 
     if (this.rq.overrideMimeType) 
     this.rq.overrideMimeType("text/xml"); 
    } else 
     this.rq = new ActiveXObject("Microsoft.XMLHTTP"); 

    try { 
     this.rq.onreadystatechange = connectionEvent; 
     this.rq.open("GET", this.source, true); 
     this.rq.send(null); 
     this.state = 1; 
    } catch (err) { 
     // some error handler here 
    } 

} 

function connectionEvent() { 
    alert("i'm here"); 
    alert("this doesnt work: " + this.someOtherProperty); 
} 

} // MyClass

так что нет ничего более, чем иметь объект XMLHttpRequest в качестве члена моего класса, вместо глобально определены и ссылаются на него традиционным способом. однако внутри моей функции callEvent callback значение «this» теряется, хотя сама функция находится внутри myClass. Я также удостоверился, что объект, который я создаю из myClass, остается достаточно длинным (объявлен глобальным в скрипте).

во всех примерах использования классов javascript, которые я видел, «это» все еще доступно внутри внутренних функций. для меня это не так, даже если я выполняю свою функцию снаружи и делаю ее myClass.prototype.connectionEvent. Что я делаю не так? Спасибо.

+0

использовать jQuery для отличного ajax. – sundowatch

+1

Добро пожаловать в Stackoverflow :) Скорее используйте 4 пробела вместо вкладок для каждого отступа.Затем, когда вы копируете здесь код, вы должны отложить * полный * фрагмент с еще 4 пробелами. Вы можете сделать это, выбрав фрагмент, а затем нажав кнопку '010101' на панели инструментов редактора сообщений или клавишу Ctrl + K. – BalusC

ответ

4

Причина, по которой это не работает, заключается в том, что в Javascript this полностью определяется тем, как функция называется, а не там, где она определена. Это отличается от некоторых других языков.

Чтобы this означать, что вы ожидаете, вы должны убедиться, что явно «связывание» это:

this.start = function() { 
    var self = this; // Set up something that survives into the closure 

    /* ...lots of stuff omitted... */ 

    this.rq.onreadystatechange = function() { 
     // Call `connectionEvent`, setting `self` as `this` within the call 
     connnectionEvent.call(self); 
    }; 

Там больше информации о this управления в this blog post, но в основном: Когда функция вызывается без особых усилий, сделанных для установки this, this внутри функции всегда будет глобальный объект (, в браузерах). Есть два способа установки this при выполнении вызова:

  1. Использование Function#call (или Function#apply), как я сделал выше, переходящий в ссылке на объект для использования в качестве this в качестве первого параметра. Это вызывает функцию и устанавливает this на то, что вы передали. Разница между #call и #apply заключается в том, как вы передаете дополнительные аргументы для перехода в функцию. С помощью #call вы передаете их в качестве дополнительных аргументов для вызова #call (например,), тогда как с #apply вы передаете их в виде массива во втором аргументе (func.apply(thisArg, [arg0, arg1, arg2])).
  2. Использование точечной нотации: если у вас есть объект с назначенной ему функцией (например, ваше свойство start), вызывая его с помощью экземпляра объекта, точки и имени свойства (this.start() или foo.start() и т. Д. .) вызовет функцию и установит this экземпляру объекта в вызове. Таким образом, пунктирная нотация делает два совершенно отличными. things: Ищет свойство и находит функцию как его значение, и вызывает функцию, так что this устанавливается на объект во время разговора. Буквально это как: var f = obj.func; f.call(obj).

Немного не по теме, но: запретив по-настоящему вескую причину, я бы не стал изобретать это колесо. Существует множество библиотек для просто вызовов XHR. jQuery, Prototype, Closure, и почти все остальное.

+0

сообщение открытия разума. Спасибо большое. (и он тоже работает, хе-хе.) –

+0

@Radu: Хорошо, рад, что помог. (Я замечаю, что вы новичок здесь: Если это ответили на ваш вопрос, нажмите галочку слева от ответа вверху. Это означает, что ваш вопрос «ответил» и называет это правильным ответом.) –

+0

@Radu: Согласитесь с TJ Lib, как jQuery, делает это намного проще, удаляя много сантехники. см. http://api.jquery.com/jQuery.ajax/ –

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