Пожалуйста, помогите мне понять этот код JavaScript из "Ajax в действии" - PullRequest
2 голосов
/ 23 марта 2011

Я видел этот код в Ajax в книге действий, и есть две вещи, которые я не могу понять (имейте в виду, я только начал веб-программирование, и я все еще пытаюсь понять, как работает JavaScript).

  1. В строке 37 или в функции loadXMLDoc, почему автор объявил локальную переменную "var loader = this;"и затем использовал его в вызове "net.ContentLoader.onReadyState.call (loader);"вместо простого использования «net.ContentLoader.onReadyState.call (this);» *

  2. Почему автор использовал «net.ContentLoader.onReadyState.call (loader);» вместо"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());
    }

1 Ответ

2 голосов
/ 23 марта 2011

Оператор try/catch в ECMA- / Javascript создает новый Context . Технически это похоже на оператор eval и, следовательно, eval Context.

Текущая цепочка областей действия расширяется вновь созданным " eval Context ", и поэтому переменная Context * this будет указывать на неправильную контекст, когда только что вызван this.onReadyState();.

Вызвав net.ContentLoader.onReadyState.call(loader);, автор явно вызывает метод onReadyState с контекстом объекта loaded (и это то, на что ссылается this внутри вызываемого ). A callee - это функция (-context ...), вызываемая вызывающей стороной (-context).


Короче говоря, ECMAscripts .call() и .apply() методы позволяют вам установить конкретный контекст для функция при вызове. Это необходимо здесь, потому что try/catch создает новый контекст и значение this в вызываемом методе быть неправым.


Хотя приведенное выше утверждение верно, здесь оно не несет ответственности. Проблема не в контексте из try / catch, а в контексте созданной анонимной функции

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

Использование this в этом анонимном методе «снова» будет ссылаться на другой контекст. Вот почему автор кэшировал значение из this в loader и вызывает метод с этим кэшированным контекстом.

...