Возможно ли иметь событие в JS, которое срабатывает при изменении значения определенной переменной? JQuery принимается.
javascript
jquery
dom-events
rashcroft22
источник
источник
variable
, но все ответы здесь относятсяproperty
. Интересно, можем ли мы прислушиваться кlocal variable
изменениям?Ответы:
Да, это теперь вполне возможно!
Я знаю, что это старый поток, но теперь этот эффект возможен с использованием методов доступа (геттеры и сеттеры): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects#Defining_getters_and_setters
Вы можете определить объект как этот, в котором
aInternal
представляет полеa
:Затем вы можете зарегистрировать слушателя, используя следующее:
Таким образом, всякий раз, когда что-либо меняет значение
x.a
, функция слушателя будет запущена. Выполнение следующей строки вызовет всплывающее окно с предупреждением:Смотрите пример здесь: https://jsfiddle.net/5o1wf1bn/1/
Вы также можете использовать массив слушателей вместо одного слота слушателя, но я хотел бы привести вам самый простой пример.
источник
this.aListener(val)
вам придется циклически перебирать все функции слушателя и вызывать каждую проходящую функциюval
. Как правило, метод вызываетсяaddListener
вместоregisterListener
.Большинство ответов на этот вопрос либо устарели, либо неэффективны, либо требуют включения больших раздутых библиотек:
Сегодня вы можете использовать объект Proxy для мониторинга (и перехвата) изменений, внесенных в объект. Он специально создан для того, что пытается сделать ОП. Вот основной пример:
Единственными недостатками
Proxy
объекта являются:Proxy
Объект не доступен в старых браузерах (таких как IE11) и polyfill не может полностью повторностиProxy
функциональность.Date
) -Proxy
объект лучше всего сочетать с простыми объектами или массивами.Если вам нужно наблюдать за изменениями, внесенными во вложенный объект , вам нужно использовать специализированную библиотеку, такую как Observable Slim (которую я опубликовал), которая работает следующим образом:
источник
target.hello_world = "test"
)you don't actually watch changes on the target object but only on proxy object
- это не совсем точно.Proxy
Объект не изменяется - это не имеет его собственную копию объекта.you just want to know when a property change on the target object
- это можно сделать с помощью aProxy
, это один из основных вариантов использования прокси.target
, то вы должны сделать это через прокси. Однакоproxy.hello_world = "test"
это не означает, что вы модифицируете прокси, прокси остается неизменным,target
модифицируется (если ваш установленный обработчик настроен для этого). Похоже, ваша точка зрения в том, что вы не можете наблюдать напрямуюtarget.hello_world = "test"
. Это правда. Простые присвоения переменных не генерируют никаких событий. Вот почему мы должны использовать инструменты, подобные описанным в ответах на этот вопрос.It sounds like your point is that you cannot directly observe target.hello_world = "test". That is true.
, это точно моя точка зрения. В моем случае у меня есть объект, созданный где-то еще и обновленный каким-то другим кодом ... прокси-сервер в этом случае бесполезен, так как изменения будут внесены в цель.Нет.
Но, если это действительно так важно, у вас есть 2 варианта (первый проверен, второй нет):
Во-первых, используйте сеттеры и геттеры, вот так:
тогда вы можете сделать что-то вроде:
затем установите слушателя как:
Во-вторых, я действительно забыл, я подам, пока я думаю об этом :)
РЕДАКТИРОВАТЬ: О, я помню :) Вы могли бы поставить часы на значение:
Учитывая myobj выше, с 'a' на нем:
источник
С помощью
Prototype
: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/definePropertyДругой пример
источник
varw
требует 2 аргумента, но часть вашего примера показывает, что функция вызывается только с параметром value.Извините, что поднял старую ветку, но вот небольшое руководство для тех, кто (как и я!) Не видит, как работает пример Эли Грея:
Надеюсь, что это может помочь кому-то
источник
Как ответ Люка Шефера ( примечание : это относится к его первоначальному сообщению; но весь смысл здесь остается действительным после редактирования ), я бы также предложил пару методов Get / Set для доступа к вашему значению.
Однако я бы предложил некоторые модификации (и именно поэтому я публикую ...).
Проблема с этим кодом заключается в том, что поле
a
объектаmyobj
доступно напрямую, поэтому можно получить к нему доступ / изменить его значение, не вызывая слушателей:Инкапсуляция
Таким образом, чтобы гарантировать, что слушатели действительно вызваны, мы должны запретить прямой доступ к полю
a
. Как это сделать? Используйте закрытие !Теперь вы можете использовать тот же метод для создания и добавления слушателей, как предложил Люк, но вы можете быть уверены, что нет никакого способа читать или писать, чтобы
a
остаться незамеченным!Добавление инкапсулированных полей программно
Продолжая следить за Люком, я предлагаю теперь простой способ добавления инкапсулированных полей и соответствующих методов получения / установки к объектам с помощью простого вызова функции.
Обратите внимание, что это будет правильно работать только с типами значений . Для этого , чтобы работать с ссылочными типами , какое - то глубокая копии должно быть выполнено (см этой , например).
Это работает так же, как и раньше: мы создаем локальную переменную для функции, а затем создаем замыкание.
Как это использовать? Просто:
источник
Если вы используете jQuery {UI} (который должен использовать каждый :-)), вы можете использовать .change () со скрытым элементом <input />.
источник
<input/>
элементу?<input type="hidden" value="" id="thisOne" />
и с JQuery,$("#thisOne").change(function() { do stuff here });
а$("#thisOne").val(myVariableWhichIsNew);
затем.change()
будет стрелять.var1 = 'new value';
, вы установите значение этого скрытого ввода, а затем добавите прослушиватель для изменения переменной.$("#val1").on('change', function(){ val1 = this.val(); ... do the stuff that you wanted to do when val1 changed... }); $("#val1").val('new value');
AngularJS
(Я знаю, что это не такJQuery
, но это может помочь. [Чистый JS хорош только в теории]):где «данные» - это имя вашей переменной в области видимости.
Есть ссылка на док.
источник
$scope.$apply()
запускеДля тех, кто занимается тюнингом через пару лет:
Доступно решение для большинства браузеров (и IE6 +), которое использует событие onpropertychange и более новую спецификацию defineProperty. Небольшая проблема в том, что вам нужно сделать вашу переменную объектом dom.
Полная информация:
http://johndyer.name/native-browser-get-set-properties-in-javascript/
источник
Функциональность, которую вы ищете, может быть достигнута с помощью метода defineProperty (), который доступен только для современных браузеров:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
Я написал расширение jQuery, которое имеет некоторые аналогичные функциональные возможности, если вам нужна дополнительная кросс-браузерная поддержка:
https://github.com/jarederaj/jQueue
источник
Не напрямую: вам нужна пара getter / setter с интерфейсом «addListener / removeListener» или плагин NPAPI (но это совсем другая история).
источник
или
или
источник
Довольно простое и упрощенное решение состоит в том, чтобы просто использовать вызов функции для установки значения глобальной переменной и никогда не устанавливать ее значение напрямую. Таким образом, вы имеете полный контроль:
Нет никакого способа обеспечить это, это просто требует дисциплины программирования ... хотя вы можете использовать
grep
(или что-то подобное), чтобы проверить, что нигде ваш код не устанавливает непосредственно значениеglobalVar
.Или вы можете инкапсулировать его в объектный и пользовательский методы getter и setter ... просто мысль.
источник
var
в модулях ES6 - это единственное решение.Пожалуйста, ребята, помните, что первоначальный вопрос был для ПЕРЕМЕННЫХ, а не для ОБЪЕКТОВ;)
в дополнение ко всем ответам выше я создал крошечную библиотеку forTheWatch.js , которая использует тот же способ для отлова и обратного вызова для изменений в обычных глобальных переменных в javascript.
Совместим с переменными JQUERY, нет необходимости использовать OBJECTS, и вы можете при необходимости напрямую передавать массив из нескольких переменных.
Если это может быть полезно ...: https://bitbucket.org/esabora/forthewatch
В основном вам просто нужно вызвать функцию:
watchIt("theVariableToWatch", "varChangedFunctionCallback");
И извините заранее, если не актуально.
источник
Самый простой способ, который я нашел, начиная с этого ответа :
А потом:
источник
В моем случае я пытался выяснить, переопределяет ли какая-либо библиотека, которую я включил в мой проект
window.player
. Итак, в начале моего кода я просто сделал:источник
Это не возможно напрямую.
Однако это можно сделать с помощью CustomEvent: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent
Приведенный ниже метод принимает массив имен переменных в качестве входных данных и добавляет прослушиватель событий для каждой переменной и запускает событие для любых изменений значения переменных.
Метод использует опрос для обнаружения изменения значения. Вы можете увеличить значение тайм-аута в миллисекундах.
Вызывая метод:
Он обнаружит изменения в переменных username и userid.
источник
С помощью getter и setter вы можете определить класс JavaScript, который делает такую вещь.
Сначала мы определяем наш класс с именем
MonitoredVariable
:Предположим, что мы хотим прослушать
money
изменения, давайте создадим экземплярMonitoredVariable
с начальными деньгами0
:Тогда мы могли бы получить или установить его значение, используя
money.val
:Поскольку мы не определили слушателей для него, ничего особенного не происходит после
money.val
изменений в 2.Теперь давайте определимся с некоторыми слушателями. У нас есть четыре слушателей доступны:
beforeSet
,beforeChange
,afterChange
,afterSet
. Следующее произойдет последовательно, когда вы используетеmoney.val = newValue
для изменения значения переменной:Теперь мы определяем
afterChange
слушателя, который будет запущен только после того, какmoney.val
он был изменен (хотяafterSet
будет активирован, даже если новое значение совпадает со старым):Теперь установите новое значение
3
и посмотрите, что произойдет:В консоли вы увидите следующее:
Полный код см. По адресу https://gist.github.com/yusanshi/65745acd23c8587236c50e54f25731ab .
источник
Это старая тема, но я наткнулся на второй по величине ответ (пользовательские слушатели), когда искал решение с использованием Angular. Несмотря на то, что решение работает, Angular имеет лучший встроенный способ решения этой проблемы с использованием источников
@Output
событий. Исходя из примера в пользовательском ответе слушателя:ChildComponent.html
ChildComponent.ts
ParentComponent.html
ParentComponent.ts
Теперь это будет обновлять
n
родительский элемент при каждом нажатии дочерней кнопки. Рабочий стекблицисточник
источник