xmlhttprequest javascript 中 "this" 范围的双重问题

Double issue with "this" scope in xmlhttprequest javascript

我的 javascript 代码中的 this 范围有两个大问题。 创建 setAJAXGet 对象后,回调函数丢失,无法正确调用。因此,我没有调用 this.funct,而是设置了 ajax.parent = this;并致电 this.parent.funct - 工作正常。

function setAJAXGet() {
    this.askServer = function() {
    var ajax = new XMLHttpRequest();
    ajax.parent = this; 
    ajax.contentType = "charset:utf-8";
    ajax.onreadystatechange = function() {
            if (ajax.readyState==4 && ajax.status==200) {
            this.parent.funct(ajax.responseText);
            }
    }
    ajax.open( "GET", this.url+'?'+this.vars, true );
    ajax.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
    if (navigator.onLine) ajax.send( null ); else this.functError();
    }
this.functError;
this.funct;
this.vars;
this.url;
}

当我尝试从另一个对象调用 setAJAXGet() 并且回调函数在该对象内部时,事情变得有点复杂。回调函数被正确调用,但对象中的所有其他函数(来自回调函数)都变得不可见。

function someObject() {
    this.asyncGet = function() {
    var get = new setAJAXGet();
    //do some config here...
    get.funct = this.processAsyncData;
    get.askServer();
    }

    this.someOtherFunction = function() {
    }

    this.processAsyncData = function(ajaxText) {
    // ajaxText is OK
    this.someOtherFunction();
    // this.someOtherFunction is not defined (how so?)
    }

this.asyncGet();
}

我可以通过修改 setAJAXGet() 作为参数将对象传递给 processAsyncData 来解决这个问题,但它看起来很难看。

function someObject() {
    this.asyncGet = function() {
    var get = new modifiedSetAJAXGet();
    //do config here...
    get.object = this; // stores 'this' and sends it to callback as argument
    get.funct = this.processAsyncData;
    get.askServer();
    }

    this.someOtherFunction = function() {
    }

    this.processAsyncData = function(object, ajaxText) {
    // ajaxText is OK
    object.someOtherFunction();
    // object.someOtherFunction works just fine
    }

this.asyncGet();
}

我相信你知道更优雅的解决方案。

很难理解你的代码的 objective,但是你在 Javascript 中需要学习的主要内容是函数中 this 的值由函数是如何被调用的。这在 Javascript 中令人困惑,直到您完全理解重要的是函数的调用方式。事物如何声明并不重要,重要的是它们如何被调用。

当你做这样的事情时:

get.funct = this.processAsyncData;

放入 get.funct 的是指向 processAsyncData 方法的指针。与 get.funct 中的 this 值完全没有任何联系。所以,当你稍后调用 get.funct() 时,它与调用 this. processAsyncData() 是不一样的。 this 的值将丢失。

这就是 .bind() 派上用场的地方。您可以阅读有关 .bind here 的内容。它所做的是创建一个临时函数存根,重新附加 this 的值,以便不会发生上述分离。所以,你可以这样使用它:

get.funct = this.processAsyncData.bind(this);

然后,当您调用 get.funct() 时,它会生成与 this.processAsyncData() 完全相同的函数调用和 this 的值,因为 .bind() 已经创建了一个函数存根以自动重新附加 this.

的所需值

正如我在之前的评论中发表的那样,在另一个答案中很好地总结了如何控制 this 的值:When you pass 'this' as an argument.

请注意,我提出的解决方案与您在评论中提到的不同。我建议您在此过程中尽早解决问题,这样 .funct 方法就可以随时被任何人调用,而无需执行任何特殊操作。