Ошибка JavaScript "не является функцией" при вызове определенного метода
Это мой код:
request_xml: function()
{
http_request = false;
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType)
{
http_request.overrideMimeType('text/xml');
}
if (!http_request)
{
return false;
}
http_request.onreadystatechange = this.response_xml;
http_request.open('GET', realXmlUrl, true);
http_request.send(null);
xmlDoc = http_request.responseXML;
},
response_xml:function ()
{
if (http_request.readyState == 4)
{
if(http_request.status == 404 && countXmlUrl<=3)
{
countXmlUrl++;
realXmlUrl = xmlUrl[countXmlUrl];
this.request_xml();
}
if (http_request.status == 200)
{
xmlDoc = http_request.responseXML;
alert("need to update3");
this.peter_save_data();
}
}
},
peter_save_data:function()
{
// removed function code
},
Странно, предупреждение срабатывает без проблем, но вызов функции под ним дает мне эту ошибку:
Error: this.peter_save_data is not a function
Вызов той же функции проклятия из другой функции в другом месте отлично работает.
Ответы
Ответ 1
Вы можете сделать это прямо перед тем, как вызвать генерацию XML.
var that = this;
и позже...
that.peter_save_data();
Поскольку this
часто изменяется при изменении области с помощью новой функции, вы не можете получить доступ к исходному значению, используя его. Слияние с ним позволяет вам получить доступ к исходному значению этого.
Ответ 2
Один важный фрагмент головоломки, который отсутствует, - это вызов response_xml
. Это важно, потому что это изменит то, что this
(см. Комментарий Jared).
Помните, что this
можно рассматривать как (грубо) "приемник вызова метода". Если response_xml
передается непосредственно для использования в качестве обратного вызова, то, конечно, это не сработает - this
, скорее всего, будет window
.
Рассмотрим следующее:
var x = {f: function () { return this }}
var g = x.f
x.f() === x // true
g() === x // false
g() === window // true
Счастливое кодирование.
"Исправить", вероятно, просто изменить способ вызова response_xml
. Существует множество способов сделать это (как правило, с закрытием).
Примеры:
// Use a closure to keep he object upon which to explicitly invoke the method
// inside response_xml "this" will be "that",
// which was "this" of the current scope
http_request.onreadystatechange = (function (that) {
return function () { return that.response_xml() }
}(this)
// Or, alternatively,
// capture the current "this" as a closed-over variable...
// (assumes this is in a function: var in global context does not create a lexical)
var self = this
http_request.onreadystatechange = function () {
// ...and invoke the method upon it
return self.response_xml()
}
Лично я просто использовал jQuery или аналогичный; -)
Ответ 3
Если вы хотите поведение класса, используйте правильный синтаксис. Библиотеки, которые его используют, используют JSON для передачи параметра функции, которая делает класс из него.
function MyClass(CTOR paarams){
var response_xml=function ()
{
if (http_request.readyState == 4)
{
if(http_request.status == 404 && countXmlUrl<=3)
{
countXmlUrl++;
realXmlUrl = xmlUrl[countXmlUrl];
this.request_xml();
}
if (http_request.status == 200)
{
xmlDoc = http_request.responseXML;
alert("need to update3");
this.peter_save_data();
}
}
}
var peter_save_data=function()
{
// removed function code
}
}
var Test = new MyClass(somthing,another_something);
Test.response_xml();
//etc etc.
Или используйте библиотеки, такие как Mootools, где вы можете сделать это как JSON:
var T = new Class({
response_xml:function ()
{
if (http_request.readyState == 4)
{
if(http_request.status == 404 && countXmlUrl<=3)
{
countXmlUrl++;
realXmlUrl = xmlUrl[countXmlUrl];
this.request_xml();
}
if (http_request.status == 200)
{
xmlDoc = http_request.responseXML;
alert("need to update3");
this.peter_save_data();
}
}
},
peter_save_data:function()
{
// removed function code
}
});
var X = new T();//etc etc