我在 Ajax in Action 一书中看到了这段代码,但有两件事我无法理解(请记住,我刚刚开始网络编程,但我仍在努力理解 JavaScript 的工作原理)。
在第 37 行或函数 loadXMLDoc 中,为什么作者要声明一个局部变量“var loader=this;”然后在调用“net.ContentLoader.onReadyState.call(loader);”时使用它而不是仅仅使用“net.ContentLoader.onReadyState.call(this);”
为什么作者使用“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()); }
最佳答案
ECMA-/Javascript 中的 try/catch
语句创建一个新的 Context。从技术上讲,这类似于 eval
语句,因此也是 eval Context
。
当前的范围链由新创建的“eval Context”扩展,因此,Context 变量 this
,当被 this.onReadyState();
调用时会指向错误的上下文。
通过调用 net.ContentLoader.onReadyState.call(loader);
作者使用 onReadyState 显式调用方法
对象(这就是 callee 中的 onReadyState
code>loadedthis
所引用的对象)。 callee 是一个函数 (-context...),由 caller (-context) 调用。
Long story short, ECMAscripts
.call()
and.apply()
methods allow you to set a specific Context for a function when invoked. This is necessary here, becausetry/catch
creates a new Context and the value ofthis
within the called method would be wrong.
虽然上述说法属实,但在此概不负责。这不是来自 try/catch
的上下文,这是问题所在,而且是创建的匿名函数的上下文
this.req.onreadystatechange=function(){
net.ContentLoader.onReadyState.call(loader);
}
在该匿名方法中使用 this
将“再次”引用不同的上下文。这就是为什么作者将 this
的值缓存在 loader
中并使用缓存的 Context 调用该方法。
关于javascript - 请帮助我理解这段来自 "Ajax in Action"的 JavaScript 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5407296/