问题说明
这改变了
The value of thisMDN has changed and is no longer referencing the expected element or value. Often this is because the scope has changed, and as a result so has the this
reference.
这包含在执行上下文中
The scope refers to the current Execution ContextECMA. In order to understand why this
has changed, it is important to understand the way these execution contexts operate in JavaScript.
执行上下文绑定 this
当控制进入执行上下文时(代码正在该范围内执行),变量的环境被设置(词法和变量环境 - 本质上,这设置了一个用于变量输入的区域,该区域已经可以访问,以及一个用于局部变量的区域存储),以及绑定this
occurs.
执行上下文的 this 绑定已更改
These contexts form a logical stack. The result is that contexts deeper in the stack have access to previous variables, but their bindings may have been altered. Every time jQuery calls a callback function, it alters the this binding by using applyMDN.
callback.apply( obj[ i ] )//where obj[i] is the current element
调用的结果apply
是 jQuery 回调函数内部,this
指回调函数正在使用的当前元素。
例如,在.each
,常用的回调函数允许.each(function(index,element){/*scope*/})
。在那个范围内,this == element
是真的。这样做的结果是,如果您期望之前的this
为了可用,它将绑定到不同的元素。
简要说明this
在 jQuery 回调中
As shown above, jQuery callbacks use the apply function to bind the function being called with the current element. This element comes from the jQuery object's element array. Each jQuery object constructed contains an array of elements which match the selectorjQuery API that was used to instantiate the jQuery object.
$(selector)
调用 jQuery 函数(记住$
是对jQuery
, code: window.jQuery = window.$ = jQuery;
)。在内部,jQuery 函数实例化一个函数对象。因此,虽然它可能不会立即显而易见,但使用$()
内部使用new jQuery()
。构建此 jQuery 对象的一部分是查找选择器的所有匹配项。然后,jQuery 对象包含与选择器匹配的 DOM 元素的类似数组的结构。
当调用 jQuery api 函数时,它将在内部迭代这个类似数组的结构。对于数组中的每个项目,它调用 api 的回调函数,绑定回调的this
到当前元素。这个调用可以在上面的代码片段中看到,其中obj
是类似数组的结构,并且i
是用于当前元素在数组中的位置的迭代器。
寻找解决方案
It can be hard to determine what happened since jQuery tends to fail silently. .data()jQuery API is still a valid call here, it just returns undefined
. As a result, the above code produces a class name of "Activate"+undefined, "Activateundefined".
这里要认识到的重要部分是 jQuery 改变了this
捆绑。为了使用之前的this
绑定时,值必须存储在变量中。存储它的通用名称是that
, self
, me
,或者在最佳实践中,对内容的实际描述this
代表。
保存绑定有效的原因是回调的执行上下文将在执行上下文堆栈中相对于绑定值的保存位置更深,从而可以访问该存储的值。
jsFiddle 演示
$('#toggleButton').click(function(){
var toggleBtn = this;
//^ store this into the toggleBtn variable
$("#toggleSet div").each(function(index,element){
//^ binds `this` to the current element
if( element.innerHTML != "Skip" ){
//^ we could have used `this.innerHTML` here
$(element).toggleClass("Activate"+$(toggleBtn).data("color"));
//^ re-use the stored `this` value
}
});
});