Сохранить доступ к этой области

У меня есть цвет, сохраненный в атрибуте данных на моей кнопке, который я хотел использовать в переключателе. Тем не менее, когда я пытался получить доступ к данным с помощью thisНет данных. Как я могу сохранить свой доступ к правильному this объем?

Я пытался переключать только данный цвет для элементов, которые не содержат Пропустить.

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 ответ

Решение

Объяснение проблемы

это изменилось

Значение this MDN изменился и больше не ссылается на ожидаемый элемент или значение. Часто это происходит потому, что сфера изменилась, и в результате this ссылка.

это содержится в контексте выполнения

Область действия относится к текущему контексту выполнения ECMA. Чтобы понять почему this изменилось, важно понимать, как эти контексты выполнения работают в JavaScript.

контексты исполнения связывают это

Когда элемент управления входит в контекст выполнения (код выполняется в этой области), среда для переменных настраивается (лексическая и переменная среды) - по сути, это устанавливает область для ввода переменных, которые уже были доступны, и область для локальных переменных, которые будут хранится), и привязка this происходит.

эта привязка была изменена для контекста выполнения

Эти контексты образуют логический стек. В результате контексты, расположенные глубже в стеке, имеют доступ к предыдущим переменным, но их привязки могут быть изменены. Каждый раз, когда jQuery вызывает функцию обратного вызова, он изменяет привязку this с помощью apply MDN.

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

Как показано выше, обратные вызовы jQuery используют функцию apply, чтобы связать функцию, вызываемую с текущим элементом. Этот элемент происходит из массива элементов объекта jQuery. Каждый созданный объект jQuery содержит массив элементов, которые соответствуют API селектора jQuery, который использовался для создания экземпляра объекта jQuery.

$(selector) вызывает функцию jQuery (помните, что $ это ссылка на jQuery, код: window.jQuery = window.$ = jQuery;). Внутренне функция jQuery создает экземпляр функционального объекта. Так что, хотя это может быть не сразу очевидно, используя $() внутренне использует new jQuery(), Частью конструкции этого объекта jQuery является поиск всех совпадений селектора. Затем объект jQuery содержит массивоподобную структуру элементов DOM, соответствующих селектору.

Когда вызывается функция API jQuery, она выполняет внутреннюю итерацию по этой структуре, подобной массиву. Для каждого элемента в массиве он вызывает функцию обратного вызова для API, связывая обратный вызов this к текущему элементу. Этот вызов можно увидеть в фрагменте кода выше, где obj является массивоподобной структурой, и i итератор, используемый для позиции в массиве текущего элемента.

Нахождение решения

Может быть трудно определить, что произошло, так как jQuery имеет тенденцию молчаливо проваливаться. .data() jQuery API по-прежнему является действительным вызовом, он просто возвращает undefined, В результате вышеприведенный код выдает имя класса "Activate" + undefined, "Activateundefined".

Здесь важно признать, что jQuery изменил this связывание. Для того, чтобы использовать предыдущий this привязка, значение должно храниться в переменной. Общее название для хранения это that, self, me или, в наилучшей практике, фактическое описание того, что 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
  }
 });
});
Другие вопросы по тегам