如果您有一个对象并为其设置属性,则可以在该对象上调用的函数中访问该属性.但是如果你调用一个函数并执行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();
Run Code Online (Sandbox Code Playgroud)
结果是:
A: my name is IceCube
B: my name is undefined
Run Code Online (Sandbox Code Playgroud)
如果响应是公开的,那么也会发生.如果xhr是公开的,这也会发生.发生了某种情况,因此调用的响应函数无法访问相同的参数.
thisJavaScript中的工作方式与其他语言(如C#或Java)的工作方式完全不同.this函数内的值完全由函数的调用方式设置,而不是在函数定义的位置.更多信息:你必须记住'这个'.
当以"正常"方式调用函数时:
foo();
Run Code Online (Sandbox Code Playgroud)
...然后在函数内,this将始终引用全局对象(在浏览器上,全局对象是window).对象实例上的一个函数没有任何关系将它"绑定"到该对象.例如:
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)
Run Code Online (Sandbox Code Playgroud)
因此,要使用正确的"上下文"(this值)调用事件处理程序,您必须采取特殊步骤,如上面链接的帖子中所述.
在您的特定情况下,由于您已经为函数定义了闭包,因此您可以使用闭包将关闭的变量轻松处理它:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
更多关于本文中的闭包,但基本上,这self是有效的,因为该变量可用于TestObject构造函数中定义的函数.您不使用this,因此您不必担心确保以this正确设置的方式调用事件处理程序.
有些原因你可能不想使用那些闭包(内存影响,如果你创建了很多TestObjects,因为每个都有TestObject自己的每个函数的副本),但是因为那已经是你如何定义对象了,所以实际上没有使用它们的成本.在这种特殊情况下,我猜测你并没有创造出数以千计的XHR响应者.
window拥有该onreadystatechange方法,因此在您的回调中,this引用window.
您可以将实例保存在 TestObject 的函数体中,var that = this然后使用that.name。这会将变量绑定到您的回调,以便它会记住自己的实例。
function getXHR(){if (window.XMLHttpRequest){return new XMLHttpRequest();}if (window.ActiveXObject){return new ActiveXObject("Microsoft.XMLHTTP");}return null;}
function TestObject()
{
var that = this;
that.name = ""; //public
var xhr = null; //private
var response = function() //private
{
if(xhr.readyState > 3)
{
alert("B: my name is " + that.name);
}
}
this.send = function() //public
{
alert("A: my name is " + that.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();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2275 次 |
| 最近记录: |