2011-03-23 2 views
2

이 코드는 Ajax in Action 책에서 보았으며 이해할 수없는 두 가지가 있습니다 (웹 프로그래밍을 시작한 것을 기억하십시오. 여전히 자바 스크립트가 어떻게 작동하는지 이해하려고 노력함)."Ajax in Action"에서이 JavaScript 코드를 이해하는 데 도움을주십시오.

  1. 온라인 또는 378 페이지의 loadXMLDoc 함수에서 작성자가 "var loader = this;"라는 로컬 변수를 선언 한 이유는 무엇입니까? 그런 다음 "net.ContentLoader.onReadyState.call (loader);"호출에서 사용했습니다. 그냥 "net.ContentLoader.onReadyState.call (this);"대신 "

  2. 왜 저자가 "this.onReadyState();"대신 "net.ContentLoader.onReadyState.call (loader);"를 사용 했습니까?

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

답변

2

ECMA-/ 자바 스크립트에서 try/catch 문은 새로운 상황을 만듭니다. 기술적으로 이는 eval 문과 유사하므로 eval Context입니다.

현재 범위 체인 그 새로 만들어진 "평가 컨텍스트"단지 this.onReadyState(); 호출시 따라서, 컨텍스트 변수this가 잘못된 컨텍스트를 가리킬 것이다 연장된다. net.ContentLoader.onReadyState.call(loader);를 호출하여

은 저자가 명시 적으로 loaded 개체의 컨텍스트와 방법을 onReadyState 호출 (그리고는 수신자this 다음 참조하는 것입니다). A 피 호출자호출자 (-context)에 의해 호출 된 with (-context ...) 함수입니다.


길고도 짧은 이야기, ECMAscripts .call().apply() 방법은 호출 할 때 당신이 기능을 위해 특정 상황을 설정할 수 있습니다. try/catch 이 새 컨텍스트를 만들고 호출 된 메서드 내에서 this의 값이 이 될 것이므로 여기에 이 필요합니다. 위의 문은 사실이지만


, 그것은 여기에 책임이 아니다. 그것은 또한 "다시"다른 컨텍스트를 참조 할 것이라고 익명 메소드 내에서 this을 사용하여 생성 된 익명 함수

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

으로 문맥의 문제입니다 try/catch에서 상황이 아니다. 이것이 저자가 this의 값을 loader에 캐싱하고 그 캐싱 된 Context로 메소드를 호출하는 이유입니다.

+0

하지만 여기에서는 "net.ContentLoader.onReadyState.call (loader);" 로더는 try/catch 블록 내에서 this와 동일합니다. 즉 try 블록 이후에 확장 된 컨텍스트를 계속 가리 킵니다.try 블록 이전에 로더 변수 생성을 옮겨서는 안된다고 말하는 것에 대해? – nik

+0

@NikhilRathod : 답변을 업데이트했습니다. 저자는 실제로'try/catch' 전에'this value'의 저장을 옮겨야합니다. 스코프 - 체인 룩업이 어쨌든이 방법을 해결할 것이기 때문에 여전히 여기에서 작동합니다. – jAndy

+0

@jAndy : 왜 그는 익명의 기능을 만들었습니까? 무엇이 잘못되었는지 "this.req.onreadystatechange = net.ContentLoader.onReadyState.call (this);" – nik

관련 문제