Прослушивание изменений переменных в JavaScript - PullRequest
391 голосов
/ 19 ноября 2009

Возможно ли иметь событие в JS, которое срабатывает при изменении значения определенной переменной? JQuery принято.

Ответы [ 18 ]

2 голосов
/ 08 марта 2014

Требуемая функциональность может быть достигнута с помощью метода defineProperty (), который доступен только для современных браузеров:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

Я написал расширение jQuery, которое имеет схожую функциональность, если вам нужна дополнительная кросс-браузерная поддержка:

https://github.com/jarederaj/jQueue

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

2 голосов
/ 19 ноября 2009

Не напрямую: вам нужен пара-метод получения / установки с каким-либо интерфейсом "addListener / removeListener" ... или плагин NPAPI (но это совсем другая история).

1 голос
/ 24 сентября 2015

Довольно простое и простое решение - просто использовать вызов функции, чтобы установить значение глобальной переменной, и никогда не устанавливать ее значение напрямую. Таким образом, у вас есть полный контроль:

var globalVar;

function setGlobalVar(value) {
    globalVar = value;
    console.log("Value of globalVar set to: " + globalVar);
    //Whatever else
}

Нет никакого способа обеспечить это, просто требуется дисциплина программирования ... хотя вы можете использовать grep (или что-то подобное), чтобы проверить, что нигде ваш код напрямую не устанавливает значение globalVar.

Или вы можете инкапсулировать его в объектный и пользовательский методы получения и установки ... просто мысль.

1 голос
/ 11 февраля 2015
//ex:
/*
var x1 = {currentStatus:undefined};
your need is x1.currentStatus value is change trigger event ?
below the code is use try it.
*/
function statusChange(){
    console.log("x1.currentStatus_value_is_changed"+x1.eventCurrentStatus);
};

var x1 = {
    eventCurrentStatus:undefined,
    get currentStatus(){
        return this.eventCurrentStatus;
    },
    set currentStatus(val){
        this.eventCurrentStatus=val;
      //your function();
    }
};

или

/*  var x1 = {
eventCurrentStatus:undefined,
currentStatus : {
    get : function(){
        return Events.eventCurrentStatus
        },
    set : function(status){
        Events.eventCurrentStatus=status;

    },
}*/
console.log("eventCurrentStatus = "+ x1.eventCurrentStatus);
x1.currentStatus="create"
console.log("eventCurrentStatus = "+ x1.eventCurrentStatus);
x1.currentStatus="edit"
console.log("eventCurrentStatus = "+ x1.eventCurrentStatus);
console.log("currentStatus = "+ x1.currentStatus);

или

/* global variable ku*/
    var jsVarEvents={};
    Object.defineProperty(window, "globalvar1", {//no i18n
        get: function() { return window.jsVarEvents.globalvarTemp},
        set: function(value) { window.window.jsVarEvents.globalvarTemp = value; }
    });
    console.log(globalvar1);
    globalvar1=1;
    console.log(globalvar1);
0 голосов
/ 05 мая 2019

Пожалуйста, ребята, помните, первоначальный вопрос был для ПЕРЕМЕННЫХ, а не для ОБЪЕКТОВ;)

в дополнение ко всем ответам выше, я создал крошечную библиотеку под названием forTheWatch.js , которые используют тот же способ для перехвата и обратного вызова для изменений в нормальных глобальных переменных в JavaScript.

Совместим с переменными JQUERY, нет необходимости использовать OBJECTS, и при необходимости вы можете передать массив из нескольких переменных.

Если это может быть полезно ...: https://bitbucket.org/esabora/forthewatch
По сути, вам просто нужно вызвать функцию:
watchIt("theVariableToWatch", "varChangedFunctionCallback");

И заранее извините, если не актуально.

0 голосов
/ 27 июня 2018

Это не возможно напрямую.

Однако это можно сделать с помощью CustomEvent: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent

Приведенный ниже метод принимает массив имен переменных в качестве входных данных и добавляет прослушиватель событий для каждой переменной и запускает событие для любых изменений значения переменных.

Метод использует опрос для обнаружения изменения значения. Вы можете увеличить значение тайм-аута в миллисекундах.

function watchVariable(varsToWatch) {
    let timeout = 1000;
    let localCopyForVars = {};
    let pollForChange = function () {
        for (let varToWatch of varsToWatch) {
            if (localCopyForVars[varToWatch] !== window[varToWatch]) {
                let event = new CustomEvent('onVar_' + varToWatch + 'Change', {
                    detail: {
                        name: varToWatch,
                        oldValue: localCopyForVars[varToWatch],
                        newValue: window[varToWatch]
                    }
                });
                document.dispatchEvent(event);
                localCopyForVars[varToWatch] = window[varToWatch];
            }
        }
        setTimeout(pollForChange, timeout);
    };
    let respondToNewValue = function (varData) {
        console.log("The value of the variable " + varData.name + " has been Changed from " + varData.oldValue + " to " + varData.newValue + "!!!"); 
    }
    for (let varToWatch of varsToWatch) {
        localCopyForVars[varToWatch] = window[varToWatch];
        document.addEventListener('onVar_' + varToWatch + 'Change', function (e) {
            respondToNewValue(e.detail);
        });
    }
    setTimeout(pollForChange, timeout);
}

Вызывая Метод:

watchVariables(['username', 'userid']);

Он обнаружит изменения в переменных username и userid.

0 голосов
/ 07 декабря 2018

Это старая ветка, но я наткнулся на второй по величине ответ (пользовательские слушатели), когда искал решение с использованием Angular. Несмотря на то, что решение работает, Angular имеет лучший встроенный способ решения этой проблемы с использованием @Output и генераторов событий. Исходя из примера в пользовательском ответе слушателя:

ChildComponent.html

<button (click)="increment(1)">Increment</button>

ChildComponent.ts

import {EventEmitter, Output } from '@angular/core';

@Output() myEmitter: EventEmitter<number> = new EventEmitter<number>();

private myValue: number = 0;

public increment(n: number){
  this.myValue += n;

  // Send a change event to the emitter
  this.myEmitter.emit(this.myValue);
}

ParentComponent.html

<child-component (myEmitter)="monitorChanges($event)"></child-component>
<br/>
<label>{{n}}</label>

ParentComponent.ts

public n: number = 0;

public monitorChanges(n: number){
  this.n = n;
  console.log(n);
}

Теперь будет обновляться n на родительском элементе при каждом нажатии дочерней кнопки. Рабочая стекблиц

0 голосов
/ 11 февраля 2015
Utils = {
    eventRegister_globalVariable : function(variableName,handlers){
        eventRegister_JsonVariable(this,variableName,handlers);
    },
    eventRegister_jsonVariable : function(jsonObj,variableName,handlers){
        if(jsonObj.eventRegisteredVariable === undefined) {
            jsonObj.eventRegisteredVariable={};//this Object is used for trigger event in javascript variable value changes ku
        }
        Object.defineProperty(jsonObj, variableName , {
                    get: function() { 
                        return jsonObj.eventRegisteredVariable[variableName] },
                    set: function(value) {
                        jsonObj.eventRegisteredVariable[variableName] = value; handlers(jsonObj.eventRegisteredVariable[variableName]);}
                    });
            }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...