保存对此范围的访问权限

时间:2014-06-11 22:10:28

标签: javascript jquery this

我的颜色存储在我的按钮上的数据属性中,我想在切换中使用。但是,当我尝试使用this访问数据信息时,没有可用的数据。如何让我访问正确的this范围?

我试图只为那些没有包含Skip的元素切换给定的颜色。

HTML

<div>
 <input id="toggleButton" type="button" value="Toggle" data-color="Red" />
</div>
<div id="toggleSet">
<div>Element</div>
 <div>Skip</div>
 <div>Element</div>
</div>

CSS

.ActivateRed{ color: red; }

JS

$('#toggleButton').click(function(){
 $("#toggleSet div").each(function(index,element){
  if( element.innerHTML != "Skip" ){
   $(element).toggleClass("Activate"+$(this).data("color"));
                                       //^this has no data to access?
                                       //Why am I getting undefined?
  }
 });
});

我的尝试是 jsFiddle 。我一直以Activateundefined作为班级名称。为什么我没有this访问我的toggleButton数据?

1 个答案:

答案 0 :(得分:9)

问题说明

这改变了

thisMDN 的值已更改,不再引用预期的元素或值。通常这是因为范围已经改变,因此this引用也是如此。

这包含在执行上下文

范围是指当前的 Execution ContextECMA 。为了理解this为什么发生了变化,理解这些执行上下文在JavaScript中的运行方式非常重要。

执行上下文绑定此

当控制进入执行上下文(代码正在该范围内执行)时,变量的环境被设置(词法和变量环境 - 基本上这为要输入的变量设置了一个区域,这个区域已经可以访问,而本地区域也是如此要存储的变量),this的绑定发生。

此绑定已针对执行上下文进行了更改

这些上下文形成逻辑堆栈。结果是堆栈中更深层次的上下文可以访问先前的变量,但它们的绑定可能已被更改。每次jQuery调用回调函数时,它都会使用 applyMDN 来改变此绑定。

callback.apply( obj[ i ] )//where obj[i] is the current element

调用apply的结果是在jQuery回调函数内部,this引用回调函数使用的当前元素。

例如,在.each中,常用的回调函数允许.each(function(index,element){/*scope*/})。在该范围内,this == element是正确的。其结果是,如果您希望以前的this可用,它将被绑定到不同的元素。

jQuery回调中this的简要说明

如上所示,jQuery回调使用apply函数将正在调用的函数与当前元素绑定。该元素来自jQuery对象的元素数组。构造的每个jQuery对象都包含一个元素数组,这些元素与用于实例化jQuery对象的 selectorjQuery API 相匹配。

$(selector)调用jQuery函数(请记住$是对jQuery的引用,代码:window.jQuery = window.$ = jQuery;)。在内部,jQuery函数实例化一个函数对象。因此,虽然可能不是很明显,但使用$()内部使用new jQuery()。构建此jQuery对象的一部分是查找选择器的所有匹配项。然后,jQuery对象包含与选择器匹配的DOM元素的类似数组的结构。

当调用jQuery api函数时,它将在内部迭代这个类似数组的结构。对于数组中的每个项,它调用api的回调函数,将回调的this绑定到当前元素。可以在上面的代码片段中看到此调用,其中obj是类似于数组的结构,i是用于当前元素数组中位置的迭代器。

寻找解决方案

由于jQuery往往会无声地失败,因此很难确定发生了什么。此处 .data()jQuery API 仍然是一个有效的调用,只返回undefined。因此,上面的代码生成了一个类名“Activate”+ undefined,“Activateundefined”。

这里要认识到的重要部分是jQuery已经改变了this绑定。为了使用先前的this绑定,该值必须存储在变量中。存储它的常用名称是thatselfme,或者在最佳实践中,是this代表的实际描述。

保存绑定的原因在于回调的执行上下文在执行上下文堆栈中相对于保存绑定值的位置更深,因此可以访问该存储的值。

jsFiddle Demo

$('#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
  }
 });
});