3

这东西几乎可以工作:

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);
}

} // 我的课

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

在我看到的所有使用 javascript 类的示例中,“this”在内部函数中仍然可用。对我来说,它不是,即使我把我的函数带到外面并将它变成一个 myClass.prototype.connectionEvent。我究竟做错了什么?谢谢你。

4

1 回答 1

6

它不起作用的原因是在 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);
    };

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

  1. 像我上面那样使用Function#call(或),传入对象引用以用作第一个参数。这将调用函数并设置为您传入的任何内容。和之间的区别在于您如何提供进一步的参数以传递给函数。您将它们作为进一步的参数提供给调用(例如),而您将它们作为数组提供给第二个参数()。Function#applythisthis#call#apply#call#callfunc.call(thisArg, arg0, arg1, arg2)#applyfunc.apply(thisArg, [arg0, arg1, arg2])
  2. 使用点分表示法:如果您的对象具有分配给它的函数的属性(如您的start属性),则通过使用对象实例、点和属性名称(this.start()foo.start()等)调用它将调用该函数并设置this为调用中的对象实例。因此,点分符号做了两件完全不同的事情:查找属性并找到一个函数作为其值,然后调用该函数,this以便在调用期间设置为对象。字面意思是:var f = obj.func; f.call(obj).

有点离题,但是:除非有很好的理由,否则我不会重新发明这个轮子。有很多库可以简单地进行 XHR 调用。jQueryPrototypeClosure以及几乎所有其他的。

于 2010-05-14T18:08:14.090 回答