2011-03-23 5 views
2

j'ai vu ce code à Ajax dans le livre d'action et il y a deux choses que je ne suis pas en mesure de comprendre (Gardez à l'esprit que je viens de commencer la programmation web et je suis essayant toujours de comprendre comment fonctionne JavaScript).S'il vous plaît me aider à comprendre ce code JavaScript de « Ajax en action »

  1. en ligne 37 ou en fonction loadXMLDoc, pourquoi l'auteur a déclaré une variable locale "var loader = ceci;" et ensuite utilisé dans l'appel "net.ContentLoader.onReadyState.call (loader);" au lieu d'utiliser simplement "net.ContentLoader.onReadyState.call (this);" Pourquoi l'auteur a-t-il utilisé "net.ContentLoader.onReadyState.call (loader);" au lieu de "this.onReadyState();"

 
    /* 
    url-loading object and a request queue built on top of it 
    */ 

    /* namespacing object */ 
    var net=new Object(); 

    net.READY_STATE_UNINITIALIZED=0; 
    net.READY_STATE_LOADING=1; 
    net.READY_STATE_LOADED=2; 
    net.READY_STATE_INTERACTIVE=3; 
    net.READY_STATE_COMPLETE=4; 


    /*--- content loader object for cross-browser requests ---*/ 
    net.ContentLoader=function(url,onload,onerror,method,params,contentType){ 
     this.req=null; 
     this.onload=onload; 
     this.onerror=(onerror) ? onerror : this.defaultError; 
     this.loadXMLDoc(url,method,params,contentType); 
    } 

    net.ContentLoader.prototype.loadXMLDoc=function(url,method,params,contentType){ 
     if (!method){ 
     method="GET"; 
     } 
     if (!contentType && method=="POST"){ 
     contentType='application/x-www-form-urlencoded'; 
     } 
     if (window.XMLHttpRequest){ 
     this.req=new XMLHttpRequest(); 
     } else if (window.ActiveXObject){ 
     this.req=new ActiveXObject("Microsoft.XMLHTTP"); 
     } 
     if (this.req){ 
     try{ 
      var loader=this; 
      this.req.onreadystatechange=function(){ 
      net.ContentLoader.onReadyState.call(loader); 
      } 
      this.req.open(method,url,true); 
      if (contentType){ 
      this.req.setRequestHeader('Content-Type', contentType); 
      } 
      this.req.send(params); 
     }catch (err){ 
      this.onerror.call(this); 
     } 
     } 
    } 


    net.ContentLoader.onReadyState=function(){ 
     var req=this.req; 
     var ready=req.readyState; 
     var httpStatus=req.status; 
     if (ready==net.READY_STATE_COMPLETE){ 
     if (httpStatus==200 || httpStatus==0){ 
      this.onload.call(this); 
     }else{ 
      this.onerror.call(this); 
     } 
     } 
    } 

    net.ContentLoader.prototype.defaultError=function(){ 
     alert("error fetching data!" 
     +"\n\nreadyState:"+this.req.readyState 
     +"\nstatus: "+this.req.status 
     +"\nheaders: "+this.req.getAllResponseHeaders()); 
    } 

Répondre

2

Une déclaration try/catch dans ECMA/Javascript crée un nouveau contexte . Techniquement, cela ressemble à une déclaration eval et donc une eval Context.

La chaîne de portée actuelle est prolongée par cette nouvelle « Contexte eval » et, par conséquent, la variable Contextethis, indiquerait un mauvais contexte quand juste invoqué par this.onReadyState();.

En appelant net.ContentLoader.onReadyState.call(loader); l'auteur appelle explicitement la méthode onReadyState avec le contexte de l'objet loaded (et c'est ce this dans le fait référence appelé alors). Un est appelé une fonction (-Contexte ...) avec a été appelé par un appelant (-Contexte).


longue histoire courte, ECMAscripts .call() et .apply() méthodes permettent vous de définir un contexte spécifique pour une fonction lorsqu'elle est invoquée. Ceci est nécessaire ici, car try/catch crée un nouveau contexte et la valeur de this dans la méthode appelée serait avoir tort.


Alors que la déclaration ci-dessus est vrai, ce n'est pas responsable ici. Ce n'est pas le contexte de try/catch qui est le problème, il est en outre le contexte de la fonction anonyme créée

this.req.onreadystatechange=function(){ 
    net.ContentLoader.onReadyState.call(loader); 
} 

En utilisant this dans cette méthode anonyme serait « à nouveau » référence à un contexte différent. Voilà pourquoi l'auteur mis en mémoire cache la valeur de this dans loader et invoque la méthode avec ce contexte mis en cache.

+0

Mais ici dans l'appel "net.ContentLoader.onReadyState.call (chargeur);" le chargeur est identique à celui-ci dans le bloc try/catch, c'est-à-dire qu'il pointe toujours vers le contexte étendu après le bloc try.Pour ce que vous dites ne devrait-il pas déplacer la création de la variable loader avant le bloc try? – nik

+0

@NikhilRathod: J'ai mis à jour la réponse. L'auteur devrait en fait déplacer le stockage de la 'this value' avant le' try/catch' en effet. Cela fonctionne toujours ici, car la recherche de la chaîne de portée résoudra la méthode de toute façon. – jAndy

+0

@jAndy: Alors pourquoi a-t-il créé une fonction anonyme? qu'est-ce qui ne va pas dans "this.req.onreadystatechange = net.ContentLoader.onReadyState.call (this);" – nik

Questions connexes