Guarda acceso a este ámbito

Tengo color almacenado en un atributo de datos en mi botón que quería usar en un interruptor. Sin embargo, cuando intenté acceder a la información de datos utilizando this , no había datos disponibles. ¿Cómo puedo mantener mi acceso al correcto this scope?

Estaba tratando de alternar solo el color dado para los elementos que no contenían Omitir.

html

 
Element
Skip
Element

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? } }); }); 

Aquí hay un jsFiddle de mi bash. Sigo recibiendo Activateundefined como el nombre de la clase. ¿Por qué this no this accediendo a los datos de mi botón de palanca?

Explicación del problema

esto cambió

El valor de this MDN ha cambiado y ya no hace referencia al elemento o valor esperado. A menudo esto se debe a que el scope ha cambiado, y como resultado también lo ha hecho this referencia.

Esto está contenido en un contexto de ejecución.

El scope se refiere al contexto de ejecución actual ECMA . Para comprender por qué ha cambiado esto, es importante comprender la forma en que funcionan estos contextos de ejecución en JavaScript.

los contextos de ejecución unen esto

Cuando el control ingresa en un contexto de ejecución (el código se está ejecutando en ese ámbito), el entorno para las variables se configura (Entornos léxico y variable: esencialmente, esto configura un área para que ingresen las variables que ya eran accesibles, y un área para que las variables locales sean almacenado), y la unión de this produce.

El enlace se cambió para el contexto de ejecución.

Estos contextos forman una stack lógica. El resultado es que los contextos más profundos en la stack tienen acceso a variables anteriores, pero sus enlaces pueden haber sido alterados. Cada vez que jQuery llama a una función de callback, altera este enlace mediante el uso de apply MDN .

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

El resultado de la apply de llamada es que dentro de las funciones de callback jQuery, this refiere al elemento actual que está utilizando la función de callback.

Por ejemplo, en .each , la función de callback que se usa comúnmente permite .each(function(index,element){/*scope*/}) . En ese ámbito, this == element es verdadero. La consecuencia de esto, es que si esperaba que this anterior estuviera disponible, estará vinculado a un elemento diferente.

Breve explicación de this en jQuery callbacks.

Como se muestra arriba, las devoluciones de llamada jQuery usan la función apply para vincular la función que se está llamando con el elemento actual. Este elemento proviene de la matriz de elementos del objeto jQuery. Cada objeto jQuery construido contiene una matriz de elementos que coinciden con la API de jQuery del selector que se utilizó para instanciar el objeto jQuery.

$(selector) llama a la función jQuery (recuerde que $ es una referencia a jQuery , código: window.jQuery = window.$ = jQuery; ). Internamente, la función jQuery crea una instancia de un objeto de función. Por lo tanto, si bien puede que no sea obvio de inmediato, usar $() internamente usa new jQuery() . Parte de la construcción de este objeto jQuery es encontrar todas las coincidencias del selector. El objeto jQuery contiene una estructura similar a una matriz de los elementos DOM que coinciden con el selector.

Cuando se llama a una función de jQuery api, se itera internamente sobre esta estructura similar a una matriz. Para cada elemento de la matriz, llama a la función de callback para la API, vinculando this con el elemento actual. Esta llamada se puede ver en el fragmento de código anterior, donde obj es la estructura similar a una matriz, e i es el iterador utilizado para la posición en la matriz del elemento actual.

Encontrar una solución

Puede ser difícil determinar qué sucedió ya que jQuery tiende a fallar en silencio. .data() jQuery API sigue siendo una llamada válida aquí, simplemente devuelve undefined . Como resultado, el código anterior produce un nombre de clase de “Activate” + undefined, “Activateundefined”.

La parte importante que hay que reconocer aquí es que jQuery ha cambiado this vinculación. Para utilizar un enlace anterior, el valor debe almacenarse en una variable. Un nombre común para almacenar esto es that , self , me , o en la mejor práctica, una descripción real de lo que this representa.

La razón por la que funciona el enlace es que el contexto de ejecución de la callback será más profundo en la stack de contexto de ejecución en relación con el lugar donde se guardó el valor de enlace, por lo que tendrá acceso a ese valor almacenado.

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 } }); });