¿Es posible tener un evento en JS que se dispara cuando cambia el valor de una determinada variable? JQuery es aceptado.
javascript
jquery
dom-events
rashcroft22
fuente
fuente
variable
, pero todas las respuestas aquí se refierenproperty
. Sinlocal variable
embargo, me pregunto si podemos escuchar los cambios.Respuestas:
Sí, esto ahora es completamente posible!
Sé que este es un subproceso antiguo, pero ahora este efecto es posible utilizando accesores (getters y setters): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects#Defining_getters_and_setters
Puede definir un objeto como este, en el que
aInternal
representa el campoa
:Luego puede registrar un oyente utilizando lo siguiente:
Entonces, cada vez que algo cambie el valor de
x.a
, se activará la función de escucha. Al ejecutar la siguiente línea, aparecerá la ventana emergente de alerta:Vea un ejemplo aquí: https://jsfiddle.net/5o1wf1bn/1/
También puede usar una variedad de oyentes en lugar de una sola ranura de escucha, pero quería darle el ejemplo más simple posible.
fuente
this.aListener(val)
, tendría que recorrer todas las funciones de los oyentes y llamar a cada uno pasarval
. Por lo general, se llama al método enaddListener
lugar deregisterListener
.La mayoría de las respuestas a esta pregunta son obsoletas, ineficaces o requieren la inclusión de grandes bibliotecas hinchadas:
Hoy, ahora puede usar el objeto Proxy para monitorear (e interceptar) los cambios realizados en un objeto. Está diseñado específicamente para lo que el OP está tratando de hacer. Aquí hay un ejemplo básico:
Los únicos inconvenientes del
Proxy
objeto son:Proxy
objeto no está disponible en navegadores antiguos (como IE11) y el polyfill no puede replicar completamente laProxy
funcionalidad.Date
): elProxy
objeto se combina mejor con objetos o matrices simples.Si necesita observar los cambios realizados en un objeto anidado , debe usar una biblioteca especializada como Observable Slim (que he publicado) que funciona así:
fuente
target.hello_world = "test"
)you don't actually watch changes on the target object but only on proxy object
Eso no es del todo exacto. ElProxy
objeto no se modifica, no tiene su propia copia del objetivo.you just want to know when a property change on the target object
- puede lograr eso con unProxy
, ese es uno de los principales casos de uso para servidores proxy.target
, debe hacerlo a través de un proxy. Sin embargoproxy.hello_world = "test"
, no significa que esté modificando el proxy, el proxy permanece sin cambios,target
se modifica (si su controlador de conjunto está configurado para hacerlo). Parece que su punto es que no puede observar directamentetarget.hello_world = "test"
. Eso es verdad. Las asignaciones de variables simples no emiten ningún tipo de evento. Es por eso que tenemos que usar herramientas como las descritas en las respuestas a esta pregunta.It sounds like your point is that you cannot directly observe target.hello_world = "test". That is true.
es exactamente mi punto. En mi caso, tengo un objeto creado en otro lugar y actualizado por algún otro código ... un proxy, en este caso, no es útil ya que los cambios se realizarán en el destino.No.
Pero, si es realmente tan importante, tiene 2 opciones (la primera se prueba, la segunda no):
Primero, use setters y getters, así:
entonces puedes hacer algo como:
luego configure al oyente como:
En segundo lugar, en realidad lo olvidé, lo enviaré mientras lo pienso :)
EDITAR: Oh, lo recuerdo :) Podrías vigilar el valor:
Dado myobj arriba, con 'a' en él:
fuente
Utilizando
Prototype
: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/definePropertyOtro ejemplo
fuente
varw
requiere 2 argumentos, pero parte de su ejemplo muestra la función que se llama con solo el parámetro de valor.Lamento mencionar un tema antiguo, pero aquí hay un pequeño manual para aquellos que (¡como yo!) No ven cómo funciona el ejemplo de Eli Grey:
Espero que esto pueda ayudar a alguién
fuente
Como la respuesta de Luke Schafer ( nota : esto se refiere a su publicación original; pero todo el punto aquí sigue siendo válido después de la edición ), también sugeriría un par de métodos Get / Set para acceder a su valor.
Sin embargo, sugeriría algunas modificaciones (y es por eso que estoy publicando ...).
Un problema con ese código es que el campo
a
del objetomyobj
es directamente accesible, por lo que es posible acceder a él / cambiar su valor sin activar los oyentes:Encapsulamiento
Entonces, para garantizar que los oyentes realmente sean llamados, tendríamos que prohibir ese acceso directo al campo
a
. ¿Cómo hacerlo? Use un cierre !Ahora puede usar el mismo método para crear y agregar a los oyentes que Luke propuso, ¡pero puede estar seguro de que no hay forma posible de leer o escribir para
a
pasar desapercibido!Agregar campos encapsulados mediante programación
Todavía en el camino de Luke, propongo ahora una forma simple de agregar campos encapsulados y los respectivos captadores / establecedores a los objetos mediante una simple llamada a la función.
Tenga en cuenta que esto solo funcionará correctamente con los tipos de valor . Para que esto funcione con los tipos de referencia , habría que implementar algún tipo de copia profunda (ver este , por ejemplo).
Esto funciona igual que antes: creamos una variable local en una función, y luego creamos un cierre.
¿Cómo usarlo? Simple:
fuente
Si usa jQuery {UI} (que todos deberían usar :-)), puede usar .change () con un elemento <input /> oculto.
fuente
<input/>
elemento oculto ?<input type="hidden" value="" id="thisOne" />
y con jQuery$("#thisOne").change(function() { do stuff here });
y$("#thisOne").val(myVariableWhichIsNew);
luego.change()
se disparará.var1 = 'new value';
, establecerá el valor de esta entrada oculta, luego agregará un oyente para cambiar la variable.$("#val1").on('change', function(){ val1 = this.val(); ... do the stuff that you wanted to do when val1 changed... }); $("#val1").val('new value');
AngularJS
(Sé que esto no es asíJQuery
, pero eso podría ayudar. [Pure JS es bueno solo en teoría]):donde "datos" es el nombre de su variable en el ámbito.
Hay un enlace a doc.
fuente
$scope.$apply()
se ejecutaPara aquellos que sintonizan un par de años después:
Hay disponible una solución para la mayoría de los navegadores (e IE6 +) que utiliza el evento onpropertychange y la nueva especificación defineProperty. El pequeño inconveniente es que necesitarás hacer de tu variable un objeto dom.
Todos los detalles:
http://johndyer.name/native-browser-get-set-properties-in-javascript/
fuente
La funcionalidad que está buscando se puede lograr mediante el uso del método "defineProperty ()", que solo está disponible para los navegadores modernos:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
He escrito una extensión jQuery que tiene una funcionalidad similar si necesita más soporte para varios navegadores:
https://github.com/jarederaj/jQueue
fuente
No directamente: necesita un par getter / setter con una interfaz "addListener / removeListener" de algún tipo ... o un complemento NPAPI (pero esa es otra historia).
fuente
o
o
fuente
Una solución bastante simple y simplista es usar una llamada de función para establecer el valor de la variable global, y nunca establecer su valor directamente. De esta manera tienes control total:
No hay forma de hacer cumplir esto, solo requiere disciplina de programación ... aunque puede usar
grep
(o algo similar) para verificar que en ninguna parte su código establece directamente el valor deglobalVar
.O podría encapsularlo en un objeto y métodos de captación y configuración de usuarios ... solo un pensamiento.
fuente
var
en los módulos ES6, esta es la única solución.Por favor, recuerden que la pregunta inicial era para VARIABLES, no para OBJETOS;)
Además de todas las respuestas anteriores, creé una pequeña lib llamada forTheWatch.js , que usa la misma forma para capturar y llamadas a los cambios en las variables globales normales en javascript.
Compatible con las variables JQUERY, no es necesario usar OBJETOS, y puede pasar directamente un ARRAY de varias variables si es necesario.
Si puede ser útil ...: https://bitbucket.org/esabora/forthewatch
Básicamente solo tiene que llamar a la función:
watchIt("theVariableToWatch", "varChangedFunctionCallback");
Y perdón por adelantado si no es relevante.
fuente
La forma más fácil que he encontrado, a partir de esta respuesta :
Y entonces:
fuente
En mi caso, estaba tratando de averiguar si alguna biblioteca que estaba incluyendo en mi proyecto estaba redefiniendo mi
window.player
. Entonces, al comienzo de mi código, acabo de hacer:fuente
No es directamente posible.
Sin embargo, esto se puede hacer usando CustomEvent: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent
El siguiente método acepta una matriz de nombres de variables como entrada y agrega un detector de eventos para cada variable y activa el evento para cualquier cambio en el valor de las variables.
El método utiliza sondeo para detectar el cambio en el valor. Puede aumentar el valor del tiempo de espera en milisegundos.
Al llamar al método:
Detectará los cambios en las variables nombre de usuario y userid.
fuente
Con la ayuda de getter y setter , puede definir una clase de JavaScript que haga tal cosa.
Primero, definimos nuestra clase llamada
MonitoredVariable
:Supongamos que queremos escuchar los
money
cambios, creemos una instanciaMonitoredVariable
con dinero inicial0
:Entonces podríamos obtener o establecer su valor usando
money.val
:Como no hemos definido ningún oyente para ello, no sucede nada especial después de los
money.val
cambios a 2.Ahora definamos algunos oyentes. Tenemos cuatro oyentes disponibles:
beforeSet
,beforeChange
,afterChange
,afterSet
. Lo siguiente sucederá secuencialmente cuando usemoney.val = newValue
para cambiar el valor de la variable:Ahora definimos el
afterChange
oyente que se activará solo después de quemoney.val
haya cambiado (mientrasafterSet
que se activará incluso si el nuevo valor es el mismo que el anterior):Ahora establezca un nuevo valor
3
y vea qué sucede:Verá lo siguiente en la consola:
Para obtener el código completo, consulte https://gist.github.com/yusanshi/65745acd23c8587236c50e54f25731ab .
fuente
Este es un hilo viejo pero me topé con la segunda respuesta más alta (escuchas personalizadas) mientras buscaba una solución usando Angular. Si bien la solución funciona, angular tiene una forma mejor integrada para resolver este uso de
@Output
emisores de eventos. Saliendo del ejemplo en la respuesta de escucha personalizada:ChildComponent.html
ChildComponent.ts
ParentComponent.html
ParentComponent.ts
Esto ahora se actualizará
n
en el padre cada vez que se haga clic en el botón hijo. Pila de trabajofuente
fuente