我经历了大量的帖子,我终于得到了我需要的东西,这要归功于:
$("a.foo").click(function(){
var that = this;
jPrompt("Type something:","","", function(r) {
$(that).text(r);
}
}
以下内容: Accessing $(this) within a callback function
我想知道是否有人可以扩展这里到底发生了什么(为什么this
没有重新分配就无法使用?)以及我应该阅读哪些核心信息?从我收集的内容来看,这可能与封闭有关......这是我在搜索时碰到的大部分内容。那是准确的吗?
就我而言,我希望执行一些代码,然后在完成ajax请求后重定向。在回调函数中,我运行$(this).attr("href")
,返回undefined。
答案 0 :(得分:3)
this
由javascript根据函数的调用方式分配。因此,当jPrompt()
调用回调时,this
函数会确定回调函数jPrompt()
中的值this
。
因此,除非jPrompt通过您传入的某个参数来保持this
的相同值,否则它可能会有不同的值。因此,您可以将其保存,以便在回调中进行访问。这是javacscript回调中非常常见的设计模式。
仅供参考,obj.method()
分配的一些方式:
this
- method()
中的obj
将设置为func.call(obj)
this
- func()
中的obj
将设置为func()
this
- window
将在func()
或undefined
中以严格模式设置为{{1}} 答案 1 :(得分:1)
问题中的代码添加了一些评论:
$("a.foo").click(function(){
var that = this; //`this` holds the a object clicked. now so does `that`!
jPrompt("Type something:","","", function(r) {
//even if `this` has a different value here, `that` still holds the a object clicked
$(that).text(r);
}
}
这是你在类似情况下经常会发现的事情。 this
与上下文有关,您经常需要在一个上下文中保留值this
并在另一个上下文中使用它。
来自ECMAScript规范的引用:
10.1.7这个
有此值与之关联 每个活动执行上下文。该 此值取决于调用者和 正在执行的代码类型 当控制进入时确定 执行上下文。
希望能回答你的问题。您还要求提供进一步阅读的资源。请访问:
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/this
这些人提供了详细而且通常非常准确的优秀文档(与谷歌搜索中经常出现的其他热门参考资料不同 - w3cshools.com我在想你!)。
答案 2 :(得分:1)
this
的含义会根据您所处的位置而变化。点击事件处理程序中的this
表示传递给this
函数的回调中jPrompt
以外的其他内容。
对于它的价值,您不需要重新分配this
,因为传递到您的处理程序的event
对象将引用currentTarget
:
$("a.foo").on("click", function (event) {
// 'this' here refers to the anchor we clicked
jPrompt("Type something:", "", "", function (r) {
// 'this' here refers to whatever jPrompt instructs
$(event.currentTarget).text(r);
}
}
答案 3 :(得分:1)
this
this
动态范围。它的行为与词法范围的所有其他变量不同。其他变量没有不同的绑定,具体取决于调用函数的 ;它们的范围来自,其中它们出现在脚本中。 this
但行为有所不同,并且可以有不同的绑定,这取决于它出现在脚本中的 where ,而不是 它的调用方式。因此,它可能成为人们学习语言的混乱源,但掌握它对于成为一名熟练的JavaScript开发人员是必要的。
由于this
是动态绑定的,因此有几种方法可以根据您调用函数的方式更改其值。
在JavaScript中执行某项功能时,默认this
为window
。
function foo() {
console.log(this);
}
foo(); // => window
可以通过多种方式更改this
值。一种方法是将函数作为对象的方法调用:
var x = {
foo: function() {
console.log(this);
}
};
x.foo(); // => This time it's the x object.
另一种方法是使用call
或apply
来告诉函数在某个对象的上下文中执行。
function foo() {
console.log(this);
}
foo.call(x); // => x object again
foo.apply(x); // => x object as well
如果您call
或apply
上null
或undefined
,则会再次出现默认行为:该函数将在window
的上下文中执行:
function foo() {
console.log(this);
}
foo.call(null); // => window
foo.apply(undefined); // => window
但请注意,在ECMAScript 5 严格模式中,this
不会默认为窗口:
(function() {
'use strict';
function foo() {
console.log(this);
}
foo(); // => undefined
foo.call(null); // => null
foo.apply(undefined); // => undefined
})();
您还可以使用this
设置bind
,以便在调用对象之前将其绑定到对象:
function foo() {
console.log(this);
}
var bar = {
baz: 'some property'
};
var foobar = foo.bind(bar);
foobar(); // => calls foo with bar as this
this
更进一步,您有时可能希望获取作用于this
的函数,并允许this
值作为函数的第一个参数传入。这对于数组方法非常有用,例如forEach
。例如,假设您正在处理一个类似于数组但实际上不是数组的对象。
var arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
'length': 3
};
如果您想使用forEach
迭代此对象,可以使用call
:
Array.prototype.forEach.call(arrayLike, function(item) {
console.log(item);
});
// Logs: a, b, c
但是,另一种选择是创建一个forEach
函数,可以直接在对象上调用:
var forEach = Function.prototype.call.bind(Array.prototype.forEach);
现在,只要您想迭代类似数组的对象,就可以使用此函数:
forEach(arrayLike, function(item) {
console.log(item);
});
// Logs: a, b, c
有时这种方法被称为“uncurrying this
”。但是,我更喜欢创建一个可以生成这些“uncurried”函数的函数,并将其称为“lazy binding”。
var lazyBind = Function.prototype.bind.bind(Function.prototype.call);
var forEach = lazyBind(Array.prototype.forEach);
var slice = lazyBind(Array.prototype.slice);
var map = lazyBind(Array.prototype.map);
forEach(arrayLike, function(u) {
console.log(u);
});
// Logs: a, b, c
var realArray = slice(arrayLike);
// Converts arrayLike into a real array
forEach(
map(arrayLike, function(u) {
return u + 'Q';
}),
function(u) {
console.log(u);
}
);
// Logs: aQ, bQ, cQ
这项技术的一个非常棒的功能是它可以用于创建安全的JavaScript,如果您不希望页面上的其他脚本窥探内部变量,这可能会有所帮助。不过,这是一种非常先进的元编程技术,你不会在日常的JavaScript中看到它。