2013-04-05 98 views
2
(function (send) { 

    XMLHttpRequest.prototype.send = function() { 

     console.log(this.onreadystatechange); //null 
     send.apply(this, arguments); 
    }; 

})(XMLHttpRequest.prototype.send); 

为什么this.onreadystatechange为空?根据this它应该存在并且类型为functionXMLHttpRequest对象上缺少onreadystatechange()

+0

,它的'null'而不是'undefined'(或抛出一个不确定的除外),这一事实应该解释 - 它只是还没有确定呢。 – Ian 2013-04-05 13:51:34

+0

该函数只是用一些日志记录封装'send'方法。由于您没有向我们展示使用它的代码,因此我们无法说出为何在调用send时函数为null。 – Quentin 2013-04-05 13:54:14

回答

9

onreadystatechange确实存在 ...这就是为什么它是null。如果它不存在,那将是undefined。这一切都取决于它是否已经设置。这显然已经是一个财产,因为它是null ...如果它不是,那将是undefined ...或至少"onreadystatechange" in this将是false

下面是一个例子:

var a = new XMLHttpRequest(); 
a.onreadystatechange = function() { 
}; 
a.send(); 

您的控制台将记录一个function

如果您有:

var b = new XMLHttpRequest(); 
b.send(); 

您的控制台将日志null

这里有这种情况发生的演示http://jsfiddle.net/3XKx7/

(我清楚地离开了其他步骤出了Ajax请求,这只是为了说明)

我不是想暗示有一个nullundefined之间的关系 - 我只是说在创建新的XMLHttpRequest时,onreadystatechange将在内部设置为null。无论您是否将其设置为功能,都取决于您。

UPDATE

创建/发送XHR方式,一般是这样的顺序:

var xhr = new XMLHttpRequest(); 
xhr.onreadystatechange = function() { // This and `open` could be flip-flopped 
    // whatever 
}; 
xhr.open("POST", url, true); 
xhr.send("data=data"); 

我总是告诉/显示创建新XMLHttpRequest,那么无论设置onreadystatechange的顺序并打电话open,但只有在这两个应该我打电话send

所以,如果总是做,onreadystatechange(如果实际设置)不会null并且将是一个function

既然你提到你使用jQuery,我决定重写send方法像你想,并使一个jQuery $.ajax通话测试(不手动发送XMLHttpRequest)。下面是我的测试 - http://jsfiddle.net/3XKx7/1/

它没有意义,为什么onreadystatechangenull,因为jQuery 是结合该事件,以请求和完成时的状态就知道了。所以我决定看看jQuery源代码。而我发现的是,他们称之为事物的顺序是:

xhr.open() 
xhr.send() 
xhr.onreadystatechange = function() { 

}; 

这意味着,当你重写send方法,onreadystatechangenull因为jQuery的不调用send之前设置它。我不知道他们的理由......可能是为了防止像你正在做的事情......但我从来没有听说过或看到这个惯例被使用。

所以你得到它的值作为null的原因是因为jQuery调用send后设置onreadystatechange。这意味着当您覆盖send并尝试访问onreadystatechange属性时,它尚未设置。

希望这是一个例子,可以帮助您了解:http://jsfiddle.net/dMP6q/16/

+0

我想拦截jQuery的Ajax调用使用此。无法弄清楚它为什么会为null(因为jQuery显然正在使用它) – Johan 2013-04-05 20:20:03

+0

@Johan Woah,我想我明白你在说什么了。是的,它为什么会被设置为null是没有意义的。以下是我用http://jsfiddle.net/3XKx7/1/测试的内容 – Ian 2013-04-05 20:59:39

+0

我应该在问题中更加清楚:/我不知道如何解决它。 – Johan 2013-04-05 21:09:08

1

你应该自己设置它,当状态改变时这个函数会被调用。这就像其他的事件处理程序,如document.onloadyourelement.onclick

古典你做

var httpRequest = new XMLHttpRequest(); 
    httpRequest.onreadystatechange = function() { 
     if (httpRequest.readyState === 4) { 
       if (httpRequest.status === 200) { 
        // use httpRequest.responseText 
       } 
     } 
    }; 
    httpRequest.open('GET', url); 
    httpRequest.send(); 
+0

随机问题 - 你知道为什么每个人(是的,包括我)总是在**回调中使用'httpRequest' **吗?为什么没有人使用'this'?这不重要,但我只是想知道。我认为我从未见过人们使用'this',但是我会为普通的事件处理程序看到它。 – Ian 2013-04-05 22:29:54

+0

我有时使用这个,但我发现使用你声明的变量是正常的:你知道它是什么,而你必须知道使用这个特定回调的上下文是什么。对于图像的加载,这也是一样的。 – 2013-04-06 06:21:17

+0

的确如此。我想我只是想设置一个函数的引用(而不是一个匿名函数),如'xhr.onreadystatechange = stateChange;',你不能在函数中使用'xhr' ...你必须使用'this'。所以对我来说,它总是使用'this',因为它应该总是引用特定的请求。无论如何,我想这不是太重要,我只是想听听你的意见。谢谢:) – Ian 2013-04-06 17:45:53