Сохранить доступ к этой области
У меня есть цвет, сохраненный в атрибуте данных на моей кнопке, который я хотел использовать в переключателе. Тем не менее, когда я пытался получить доступ к данным с помощью 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
представляет собой.
Причина сохранения привязки работает в том, что контекст выполнения обратного вызова будет глубже в стеке контекста выполнения относительно того, где было сохранено значение привязки, таким образом, имея доступ к этому сохраненному значению.
$('#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
}
});
});