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

发布于 2024-09-01 06:18:23 字数 1084 浏览 5 评论 0 原文

这件事几乎可以工作:

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

} // myClass

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

在我看到的所有使用 javascript 类的示例中,“this”在内部函数中仍然可用。对我来说,事实并非如此,即使我将函数放在外面并将其设为 myClass.prototype.connectionEvent。我做错了什么?谢谢。

this thing almost works:

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

} // myClass

so it's nothing more than having the XMLHttpRequest object as a member of my class, instead of globally defined, and invoking it in the traditional way. however, inside my connectionEvent callback function, the meaning of "this" is lost, even though the function itself is scoped inside myClass. i also made sure that the object that i instantiate from myClass is kept alive long enough (declared global in the script).

in all the examples of using javascript classes that i saw, "this" was still available inside the inner functions. for me, it is not, even if i take my function outside and make it a myClass.prototype.connectionEvent. what am i doing wrong? thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

寻梦旅人 2024-09-08 06:18:23

它不起作用的原因是,在 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 管理的更多信息//blog.niftysnippets.org/2008/04/you-must-remember-this.html" rel="noreferrer">这篇博文,但基本上是:当一个函数被调用而没有任何特别的努力时设置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 属性),请使用对象实例、点和属性名称 (< code>this.start() 或 foo.start() 等)将调用该函数并将 this 设置为调用中的对象实例。因此,点分符号做了两件完全不同的事情:查找属性并找到一个函数作为其值,然后调用该函数,以便在调用期间将 this 设置为该对象。称呼。从字面上看,它就像: var f = obj.func; f.call(obj)。

有点偏离主题,但是:除非有充分的理由,否则我不会重新发明这个轮子。有很多库可以简单地进行 XHR 调用。 jQuery原型关闭,以及几乎所有其他内容。

The reason it's not working is that in Javascript, this is defined entirely by how a function is called, not where it's defined. This is different than some other languages.

To have this mean what you expect, you'd have to ensure that explicitly by "binding" it:

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

There's more information about this management in this blog post, but basically: When a function is called without any particular effort made to set this, this within the function will always be the global object (window, on browsers). There are two ways to set this when making a call:

  1. Using Function#call (or Function#apply) as I did above, passing in the object reference to use as this as the first parameter. That calls the function and sets this to whatever you passed in. The difference between #call and #apply is how you supply further arguments to pass into the function. With #call you supply them as further arguments to the #call call (e.g. func.call(thisArg, arg0, arg1, arg2)), whereas with #apply you supply them as an array in the second argument (func.apply(thisArg, [arg0, arg1, arg2])).
  2. Using dotted notation: If you have an object that has a property with a function assigned to it (like your start property), calling it by using the object instance, a dot, and the property name (this.start() or foo.start(), etc.) will call the function and set this to the object instance within the call. So the dotted notation does two entirely distinct things: Looks up the property and finds a function as its value, and calls the function such that this is set to the object during the call. Literally it's like: var f = obj.func; f.call(obj).

Slightly off-topic, but: Barring a really good reason to, I wouldn't reinvent this wheel. There are lots of libraries out there to simply XHR calls. jQuery, Prototype, Closure, and nearly all the rest.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文