0

当我在 IE 中运行以下代码时,它运行良好。

但在 mozilla ff 中,layerId 的值为空,因为reqGetSubMenuRef22.responseText在 line1 处为空。

function ajaxFunctionCallGetSubMenuRef22(url)
{
    if (window.XMLHttpRequest) { // Non-IE browsers and IE>=7
      reqGetSubMenuRef22 = new XMLHttpRequest();

      reqGetSubMenuRef22.onreadystatechange = processStateChangeGetSubMenuRef22;
      try {
        reqGetSubMenuRef22.open("GET", url, true);
        (( reqGetSubMenuRef22.setRequestHeader && method == "GET" ) ?  reqGetSubMenuRef22.setRequestHeader("Content-Type", "application/x-www-form-urlencoded") : reqGetSubMenuRef22 );
      } catch (e) {
        alert(e);
      }
      reqGetSubMenuRef22.send(null);
    } 
    else if (window.ActiveXObject) { // IE    
      reqGetSubMenuRef22 = new ActiveXObject("Microsoft.XMLHTTP");
      if (reqGetSubMenuRef22) {
        reqGetSubMenuRef22.onreadystatechange = processStateChangeGetSubMenuRef22;
        reqGetSubMenuRef22.open("GET", url, true);
        reqGetSubMenuRef22.send();
      }
    }
}

function processStateChangeGetSubMenuRef22() 
{

    if (reqGetSubMenuRef22.readyState == 4) { // Complete
      if (reqGetSubMenuRef22.status == 200) { // OK response
            var textToSplit = reqGetSubMenuRef22.responseText; //line1

        if(textToSplit != null && textToSplit != '') {
                subMenuRef = textToSplit;
                }
            else {
                subMenuRef='';
                }

        layerId=subMenuRef;
4

1 回答 1

0

processStateChangeGetSubMenuRef22(不是最好的函数名称顺便说一句)是一个回调。它是在reqGetSubMenuRef22's 上下文中调用的,所以不要使用 using if (reqGetSubMenuRef22.readyState === 4),而是尝试使用if (this.readyState === 4 && this.status === 200)
该函数被引用为readystatechange变量 的事件处理程序reqGetSubMenuRef22,因此该函数将是 的方法reqGetSubMenuRef22,逻辑上(在这种情况下)它被引用为this

只是用一个类比来澄清这一点:你不会把你的客厅称为Some Blvd Nr 的客厅。123,无论哪个城市,哪个国家,你都喜欢吗?当人们过来时,你说这是我的客厅,这是我们的家,这是我住的地方......

reqGetSubMenuRef22您的代码中似乎也是一个全局变量,您需要解决这个问题。在 MDN上阅读更多关于 JS 的this内容,并且,在 ajax 调用的情况下,进入closures.


function readyStateCallback()
{
    if (this.readyState === 4 && this.status === 200)
    {
        console.log(this.responseText);
        //JSON string?:
        var resp = JSON.parse(this.responseText);
        //just txt:
        var resp = this.responseText;
        //HTML?
        document.getElementById('showResponseHere').innerHTML = this.responseText;
        //many more things you can do here...
    }
}

为什么reqGetSubMenuRef22不再工作了:

function sendRequest(str)
{
    var reqGetSubMenuRef22;//<-- local scope, only accessible in function
    var i;//local, too but different
    //try catch stuff: reqGetSubMenuRef22 is now an ajax object
    for (i=0;i<str.length;i++)
    {
        console.log(i);//just an example, you'll see why
    }
    reqGetSubMenuRef22.onreadystatechange = readyStateCallback;//reqGetSubMenuRef22 is still local
    //setup reqGetSubMenuRef22, then:
    reqGetSubMenuRef22.send();
}//end function

当 sendRequest 函数返回时,所有局部变量都被 GC 处理,变量i从内存中删除。reqGetSubMenuRef22也应该是,但是它附加了一个事件,并且该事件将触发一个在全局范围或另一个仍然存在的范围中声明的函数。
该对象保持活动状态,因为 JS 正在侦听reqGetSubMenuRef22对象上的 onreadystatechange 事件。因此,即使它的名称不再与任何东西相关联,该对象仍然非常“在那里”。不是全局对象(又名窗口)调用该readyStateCallback函数,而是 ajax 对象(reqGetSubMenuRef22)调用。因此,您可以使用从该函数内部访问 ajax 对象,this该对象将始终指向调用该函数的对象。(像这样调用相同的函数readyStateCallback();, 这将指向全局对象 ( window)) 在回调完成它的工作之后this,或者 ajax 对象将被垃圾收集,除非有其他事件要发生,或者它仍然在程序中的其他地方引用。

我在解释这些东西方面很糟糕,而且我很清楚我在这里过度简化了事情,到处走捷径。但请务必阅读thisJavaScript。
顺便说一句:在函数返回后仍然保持活动状态的对象实际上是某种闭包:变量超出范围,但仍然可以引用。归根结底就是这样,这允许一些非常强大的构造,所以我敦促你也研究一下!

于 2012-07-18T09:52:50.913 回答