JavaScript "is not a function" error when calling defined method
This is my code:
request_xml: function()
{
http_request = false;
开发者_StackOverflow中文版 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
},
Strangely, the alert fires without a problem but the function call underneath gives me this error:
Error: this.peter_save_data is not a function
Calling the same function from another function elsewhere works fine.
You could do this, right before you call the XML generation.
var that = this;
and later...
that.peter_save_data();
Because this
frequently changes when changing scope by using a new function, you can't access the original value by using it. Aliasing it to that allows you still to access the original value of this.
One important piece of the puzzle that is missing is how response_xml
is being called. This is important, because it will change what this
is (see Jared's comment).
Remember that this
can be thought of as (roughly) "the receiver of the method call". If response_xml
is passed directly to use as a callback then of course it won't work -- this
will likely be window
.
Consider these:
var x = {f: function () { return this }}
var g = x.f
x.f() === x // true
g() === x // false
g() === window // true
Happy coding.
The "fix" is likely just to change how response_xml
is being called. There are numerous ways to do this (generally with a closure).
Examples:
// 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()
}
Personally, I would just use jQuery or similar ;-)
If you want a class-like behavior, use the right syntax, The libraries that use that, are using JSON to pass a parameter to a function that makes a class out of it.
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.
Or, use the libraries like Mootools where you can do it as 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
精彩评论