2011-06-11 20 views
15

definido Este es mi código:JavaScript "no es una función" error al llamar al método

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 
}, 

Curiosamente, los fuegos de alerta sin ningún problema, pero la llamada de función debajo de mí da este error:

Error: this.peter_save_data is not a function 

Llamar a la misma maldita función desde otra función en otro lugar funciona bien.

+4

Me imagino que es porque estás usando 'this' en el ámbito mal. ¿Has intentado pasarlo a la función 'peter_save_data()' pero llamándolo como 'objWhatever.peter_save_data (this)'? –

+0

Ese no es el código completo. Una pieza importante del rompecabezas que falta es * cómo se llama 'response * xml'; esto es importante, porque cambiará lo que es 'this' (ver el comentario de Jared). Recuerde que "esto" puede ser considerado como "el receptor de la llamada al método". –

+0

¿Por qué no llamarlo con su nombre calificado? –

Respuesta

24

Puede hacerlo, justo antes de llamar a la generación de XML.

var that = this; 

y después ...

that.peter_save_data(); 

Debido this cambio a menudo cuando se cambia el alcance mediante el uso de una nueva función, no se puede acceder al valor original mediante el uso de la misma. Si lo alias a eso, aún puedes acceder al valor original de esto.

+2

Considero que una variable global potencialmente innecesaria, que podría ser difícil de depurar (por ejemplo, si ya es usado por otra cosa o configurado en otro lugar y no se borra cuando el método está completo). –

+0

Esa variable no necesita ser global. Debe declararse localmente, solo antes de que cambie el contexto. –

6

Una pieza importante del rompecabezas que falta es cómo se llama alresponse_xml. Esto es importante, porque cambiará lo que this es (ver el comentario de Jared).

Recuerde que this se puede considerar como (más o menos) "el receptor de la llamada al método". Si response_xml se pasa directamente para usar como una devolución de llamada, por supuesto, no funcionará - this será probablemente window.

Considere estos:

var x = {f: function() { return this }} 
var g = x.f 
x.f() === x // true 
g() === x  // false 
g() === window // true 

feliz de codificación.


La "solución" es probable que sólo para cambiar la forma en que se está llamando response_xml. Hay numerosas formas de hacerlo (generalmente con un cierre).

Ejemplos:

// 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() 
} 

Personalmente, yo sólo uso jQuery o similares ;-)

+0

Editado el código para agregar cómo se llama a response_xml. – Ryan

+1

@Ryan Respuesta actualizada para una solución ;-) –

+0

He votado por su comentario, pero para un principiante como yo es un poco difícil de entender. Aunque ambas soluciones funcionan, estoy usando la de abajo (más simple en mi cabeza), así que acepté esa como respuesta. Espero que no te importe, ojalá pudiera elegir dos respuestas aquí, ¡y gracias! – Ryan

-1

Si desea un comportamiento similar a la clase, utilice la sintaxis correcta, Las bibliotecas que utilizan dicho, son usando JSON para pasar un parámetro a una función que hace una clase fuera de él.

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. 

O bien, utilizar las bibliotecas como Mootools donde se puede hacer como 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 
Cuestiones relacionadas