Javascript 回调中的 `this` 和作用域
`this` and scope in Javascript callback
我直接展示代码:
disable: function(e){
that = this;
var haha = this;
$.post(url, function(){
console.log(this);// (why ajax object here?
console.log(that);// (I understand this one works
console.log(haha);// ReferenceError
})
}
我在这里感到困惑的是:
- 为什么回调中的
this
不引用外部?我认为回调中的this
遵循默认的绑定角色。
- 为什么
haha
不是指that
呢?我认为当在本地范围内找不到 haha
时,它将转到外部范围。
我知道使用 that
不是一个好方法。这就是我尝试 haha
但失败的原因。
我认为您正在尝试从控制台访问这些值...在这种情况下,haha
将不起作用,因为它是函数的本地值,而您已将 that
创建为全局变量(因为没有使用 var
)。
但这是一个错误的模式,因为某些其他脚本可能会在 ajax 请求完成之前修改 that
的值。
回调函数在它自己的不同范围内运行,因此 this 指的是它,而不是它定义的地方。您可以使用绑定或应用或调用函数来绑定它。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
所以 this 指的是别的东西,但是因为它是在函数声明的范围内声明的,所以它仍然存在。
问题 1 的答案是:因为您可以在 Javascript 中随意重新绑定它,而 jQuery 恰好适用于 jQuery.post()
,如 the documentation for jQuery.ajax()
所述:
The this
reference within all callbacks is the object in the context
option passed to $.ajax
in the settings; if context
is not specified, this
is a reference to the Ajax settings themselves.
通常:您可能永远不应该依赖 Javascript 库来 而不是 重新绑定 this
。如果您在嵌套回调中需要它的值,只需保存它。在不同名称的变量中,或使用 Function.bind()
:
$(function() {
var self = this;
$.post("/echo/json/", (function() {
console.log("self", self); // this will be the document itself
console.log("this", this); // as will self
console.log("self === this", self === this); // should output true
}).bind(this));
});
jsFiddle 示例:https://jsfiddle.net/millimoose/Lx2oxobg/。对于它的价值,我强烈更喜欢使用单独的变量来提高可读性,因为你可以给它一个描述性的名称,而且 this
不是反弹的事实,而且您已经有效地重新分配了回调的一个参数,并没有一直隐藏 在 块之后 这适用于此。
关于你的问题2,我无法重现,请看我的第二个fiddle:https://jsfiddle.net/millimoose/zL352rzf/。正如其他人所说,根据您的屏幕截图,您可能实际上并没有从 console.log()
本身获得 ReferenceError
。
尝试使用 $.ajax()
的 context
选项设置 success
的 this
,error
回调
disable: function(e) {
$.ajax({
context: this
, type:"POST"
, url:url
, success: function() {
console.log(this);
}
, error: function() {
console.log(this)
}
})
}
我直接展示代码:
disable: function(e){
that = this;
var haha = this;
$.post(url, function(){
console.log(this);// (why ajax object here?
console.log(that);// (I understand this one works
console.log(haha);// ReferenceError
})
}
我在这里感到困惑的是:
- 为什么回调中的
this
不引用外部?我认为回调中的this
遵循默认的绑定角色。 - 为什么
haha
不是指that
呢?我认为当在本地范围内找不到haha
时,它将转到外部范围。
我知道使用 that
不是一个好方法。这就是我尝试 haha
但失败的原因。
我认为您正在尝试从控制台访问这些值...在这种情况下,haha
将不起作用,因为它是函数的本地值,而您已将 that
创建为全局变量(因为没有使用 var
)。
但这是一个错误的模式,因为某些其他脚本可能会在 ajax 请求完成之前修改 that
的值。
回调函数在它自己的不同范围内运行,因此 this 指的是它,而不是它定义的地方。您可以使用绑定或应用或调用函数来绑定它。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
所以 this 指的是别的东西,但是因为它是在函数声明的范围内声明的,所以它仍然存在。
问题 1 的答案是:因为您可以在 Javascript 中随意重新绑定它,而 jQuery 恰好适用于 jQuery.post()
,如 the documentation for jQuery.ajax()
所述:
The
this
reference within all callbacks is the object in thecontext
option passed to$.ajax
in the settings; ifcontext
is not specified,this
is a reference to the Ajax settings themselves.
通常:您可能永远不应该依赖 Javascript 库来 而不是 重新绑定 this
。如果您在嵌套回调中需要它的值,只需保存它。在不同名称的变量中,或使用 Function.bind()
:
$(function() {
var self = this;
$.post("/echo/json/", (function() {
console.log("self", self); // this will be the document itself
console.log("this", this); // as will self
console.log("self === this", self === this); // should output true
}).bind(this));
});
jsFiddle 示例:https://jsfiddle.net/millimoose/Lx2oxobg/。对于它的价值,我强烈更喜欢使用单独的变量来提高可读性,因为你可以给它一个描述性的名称,而且 this
不是反弹的事实,而且您已经有效地重新分配了回调的一个参数,并没有一直隐藏 在 块之后 这适用于此。
关于你的问题2,我无法重现,请看我的第二个fiddle:https://jsfiddle.net/millimoose/zL352rzf/。正如其他人所说,根据您的屏幕截图,您可能实际上并没有从 console.log()
本身获得 ReferenceError
。
尝试使用 $.ajax()
的 context
选项设置 success
的 this
,error
回调
disable: function(e) {
$.ajax({
context: this
, type:"POST"
, url:url
, success: function() {
console.log(this);
}
, error: function() {
console.log(this)
}
})
}