javascript类在内部调用XMLHttpRequest,然后处理onreadystatechange

Rad*_*u M 3 javascript properties class xmlhttprequest onreadystatechange

这件事几乎有效:

function myClass(url) {

this.source = url;
this.rq = null;
this.someOtherProperty = "hello";

// open connection to the ajax server
this.start = function() {
    if (window.XMLHttpRequest) {
        this.rq = new XMLHttpRequest();
        if (this.rq.overrideMimeType)
        this.rq.overrideMimeType("text/xml"); 
    } else
        this.rq = new ActiveXObject("Microsoft.XMLHTTP");

    try {
        this.rq.onreadystatechange = connectionEvent;
        this.rq.open("GET", this.source, true);
        this.rq.send(null);
        this.state = 1;
    } catch (err) {
        // some error handler here
    }

}

function connectionEvent() {
    alert("i'm here");
    alert("this doesnt work: " + this.someOtherProperty);
}
Run Code Online (Sandbox Code Playgroud)

} // 我的课

所以它只不过是将XMLHttpRequest对象作为我的类的成员而不是全局定义,并以传统方式调用它.但是,在我的connectionEvent回调函数中,"this"的含义丢失了,即使函数本身是在myClass中的作用域.我还确保我从myClass实例化的对象保持足够长的时间(在脚本中声明为全局).

在我看到的所有使用javascript类的例子中,"this"仍在内部函数中可用.对我来说,它不是,即使我把我的函数带到外面并使它成为myClass.prototype.connectionEvent.我究竟做错了什么?谢谢.

T.J*_*der 5

它不起作用的原因是在Javascript中,this完全由函数的调用方式定义,而不是定义它的位置.这与其他一些语言不同.

为了达到this你的期望,你必须通过"绑定"它来明确地确保它:

this.start = function() {
    var self = this; // Set up something that survives into the closure

    /* ...lots of stuff omitted... */

    this.rq.onreadystatechange = function() {
        // Call `connectionEvent`, setting `self` as `this` within the call
        connnectionEvent.call(self);
    };
Run Code Online (Sandbox Code Playgroud)

this这篇博客文章中有更多关于管理的信息,但基本上是:当一个函数被调用而没有特别努力设置时this,this函数内将始终是全局对象(window在浏览器上).this拨打电话时有两种设置方式:

  1. 使用Function#call(或Function#apply)如上所述,传入对象引用以this用作第一个参数.它调用函数并设置this为传入的任何内容.#call和之间的区别在于#apply如何提供进一步的参数以传递给函数.与#call您提供它们作为进一步的参数给#call呼叫(例如func.call(thisArg, arg0, arg1, arg2)),而用#apply你提供它们作为一个阵列中的第二个参数(func.apply(thisArg, [arg0, arg1, arg2])).
  2. 使用点分表示法:如果您的对象具有分配了函数的属性(如您的start属性),则使用对象实例,点和属性名称(this.start()foo.start()等)调用该函数将调用该函数并设置this为调用中的对象实例.因此,虚线表示法有两个完全不同的东西:查找属性并查找函数作为其值,并调用this在调用期间设置为对象的函数.字面意思是:var f = obj.func; f.call(obj).

稍微偏离主题,但是:除非有一个非常好的理由,否则我不会重新发明这个轮子.只有XHR调用有很多库.jQuery,Prototype,Closure,以及几乎所有其他内容.