ajax 请求返回后,Javascript 对象属性变为未定义

标签 javascript ajax

如果您有一个对象并为其设置了属性,则可以在对该对象调用的函数中访问该属性。但是,如果您调用一个函数并执行 ajax 请求,以便从 onreadystatechange 调用另一个函数,则该辅助响应函数无权访问该属性。这有点令人困惑,所以看看我在这里的意思。属性 this.name 会发生变化。

//from W3Schools website
function getXHR(){if (window.XMLHttpRequest){return new XMLHttpRequest();}if (window.ActiveXObject){return new ActiveXObject("Microsoft.XMLHTTP");}return null;}

function TestObject()
{
    this.name = "";            //public
    var xhr = null;            //private
    var response = function()  //private
    {
        if(xhr.readyState > 3)
        {
            alert("B: my name is " + this.name);
        }
    }
    this.send = function()     //public
    {
        alert("A: my name is " + this.name);
        if(xhr === null)
        {
            xhr = getXHR();
        }
        var url = "http://google.com";
        xhr.onreadystatechange = response;
        xhr.open("GET", url, true);
        xhr.send(null);          
    }
}
var o = new TestObject();
o.name = "Ice Cube";
o.send();

结果是:

A: my name is IceCube
B: my name is undefined

如果响应是公开的,也会发生这种情况。如果 xhr 是公开的,也会发生这种情况。发生某些事情,导致调用的响应函数无法访问相同的参数。

最佳答案

this 在 JavaScript 中的工作方式与在其他一些语言(如 C# 或 Java)中的工作方式截然不同。函数中this 的值完全由函数调用 的方式设置,而不是函数定义 的位置。更多信息: You Must Remember 'this' .

当以“正常”方式调用函数时:

foo();

...然后在函数内,this 将始终引用全局对象(在浏览器中,全局对象是window)。对象实例上的函数没有任何内容可以将它“绑定(bind)”到该对象。例如:

var obj = {
    name: "Joe",
    speak: function() {
        alert("I'm " + this.name);
    }
};
obj.speak(); // alerts "I'm Joe"
var f = obj.speak;
f();         // alerts "I'm " (this.name is undefined within the call)

因此,要获得使用正确“上下文”(this 值)调用的事件处理程序,您必须采取特殊步骤,如 post linked above 中所述。 .

在您的特定情况下,因为您已经定义了 closures对于您的函数,您可以轻松地使用闭包关闭的变量来处理它:

function TestObject()
{
    var self;

    // Set up a variable referencing `this`
    self = this;

    // From here on out, use it instead of `this`

    self.name = "";            //public
    var xhr = null;            //private
    var response = function()  //private
    {
        if(xhr.readyState > 3)
        {
            alert("B: my name is " + self.name);
        }
    }
    self.send = function()     //public
    {
        alert("A: my name is " + self.name);
        if(xhr === null)
        {
            xhr = getXHR();
        }
        var url = "http://google.com";
        xhr.onreadystatechange = response;
        xhr.open("GET", url, true);
        xhr.send(null);
    }
}

关于闭包的更多信息 in this article ,但基本上,这是有效的,因为 self 变量可用于 TestObject 构造函数中定义的函数。您不使用 this,因此您不必担心确保以正确设置 this 的方式调用事件处理程序。

您可能有一些原因不想使用这些闭包(内存影响,如果您创建了很多 TestObject,因为每个 TestObject 都有自己的 <每个函数的 strong>copy),但由于这已经是您定义对象的方式,因此使用它们实际上没有任何成本。在这种特殊情况下,我猜您不会创建数以千计的 XHR 响应程序。

关于ajax 请求返回后,Javascript 对象属性变为未定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3063727/

相关文章:

javascript - 如何在刷新时保持我在页面上的位置(AJAX)

javascript - 防止 AJAX 内存泄漏

php - ob_clean() 清除所有级别的ob?

javascript - 如何选择表中的那些td?

javascript - 从 Bootstrap 下拉列表中获取选定的选项

javascript - 如何将倒计时卡住在 00 :00:00:00 when timer is ends

javascript - 尝试将新节点附加到现有节点不适用于自定义架构

javascript - Backbone.View.model.on ('change:...' ) 只触发一次

javascript - 整齐地对齐动态输入

javascript - 通过 AJAX onclick 传递数据