请帮助我理解“Ajax in Action”中的这段 JavaScript 代码。
我在 Ajax in Action 书中看到了这段代码,有两件事我无法理解(请记住,我刚刚开始 Web 编程,并且仍在尝试了解 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()); }
I saw this code in Ajax in Action book and there are two things I'm not able to understand (Keep in mind I just started web programming and I'm still trying to understand how JavaScript works).
On line 37 or in function loadXMLDoc, why did the author declared a local variable "var loader=this;" and then used it in the call "net.ContentLoader.onReadyState.call(loader);" instead of just using "net.ContentLoader.onReadyState.call(this);"
Why did the author used "net.ContentLoader.onReadyState.call(loader);", instead of "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()); }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
ECMA-/Javascript 中的try/catch
语句创建一个新的 Context。从技术上讲,这类似于eval
语句,因此类似于eval Context
。当前的作用域链由新创建的作用域链扩展“eval Context”,因此 Context 变量
this
在通过this.onReadyState( 调用时会指向错误的上下文);
。通过调用net.ContentLoader.onReadyState.call(loader);
,作者使用loaded
的上下文显式调用方法onReadyState
对象(这就是被调用者中的this
所引用的内容)。 被调用者是一个被调用者(-context)调用的函数(-context...)。虽然上述说法属实,但在此不负任何责任。问题不是来自
try / catch
的上下文,而是创建的匿名函数的上下文,在该匿名方法中使用
this
会“再次”引用不同的上下文。这就是为什么作者将this
的值缓存在loader
中,并使用缓存的 Context 调用该方法。Atry/catch
statement in ECMA-/Javascript creates a new Context. Technically, this is similar to aneval
statement and therefore aneval Context
.The current Scope chain is extended by that newly created "eval Context" and therefore, the Context variable
this
, would point to a wrong context when just invoked bythis.onReadyState();
.By callingnet.ContentLoader.onReadyState.call(loader);
the author explicitly calls the methodonReadyState
with the context of theloaded
object (and that is whatthis
within the callee is referencing then). A callee is a function (-context...) with was called by a caller (-context).While the above statement is true, it's not responsible here. It's not the Context from
try / catch
which is the problem , it's furthermore the Context by the created anonymous functionUsing
this
within that anonymous method would "again" reference a different Context. That is why the author cached the value fromthis
inloader
and invokes the method with that cached Context.