是否有可能在JS中有一个事件,当某个变量的值发生变化时触发?JQuery被接受。


当前回答

一个相当简单和简单的解决方案是只使用函数调用来设置全局变量的值,而不要直接设置它的值。这样你就可以完全控制:

var globalVar;

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

没有办法强制执行,它只需要编程纪律……尽管你可以使用grep(或类似的东西)来检查你的代码没有直接设置globalVar的值。

或者你可以把它封装在一个对象和用户getter和setter方法中…只是一个想法。

其他回答

你正在寻找的功能可以通过使用“defineProperty()”方法来实现——这只适用于现代浏览器:

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

我写了一个jQuery扩展,有一些类似的功能,如果你需要更多的跨浏览器支持:

https://github.com/jarederaj/jQueue

对象的队列回调的jQuery小扩展 变量、对象或键的存在。你可以分配任意数量的 对可能受影响的任意个数的数据点的回调 进程在后台运行。jQueue监听并等待 您指定的这些数据开始存在,然后发射 纠正回调函数的参数。

在我的情况下,我试图找出我的项目中包含的任何库是否重新定义了我的window.player。所以,在我的代码的开始,我只是做了:

Object.defineProperty(window, 'player', {
  get: () => this._player,
  set: v => {
    console.log('window.player has been redefined!');
    this._player = v;
  }
});

这是不可能的。

但是,这可以使用CustomEvent: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent来完成

下面的方法接受一个变量名数组作为输入,并为每个变量添加事件侦听器,并在变量值发生任何更改时触发事件。

该方法使用轮询来检测值的变化。您可以以毫秒为单位增加timeout的值。

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的更改。

是的,现在这是完全可能的!

我知道这是一个旧线程,但现在这种效果是可能使用访问器(getter和setter): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects#Defining_getters_and_setters

你可以像这样定义一个对象,其中inner表示字段a:

x = {
  aInternal: 10,
  aListener: function(val) {},
  set a(val) {
    this.aInternal = val;
    this.aListener(val);
  },
  get a() {
    return this.aInternal;
  },
  registerListener: function(listener) {
    this.aListener = listener;
  }
}

然后你可以使用下面的方法注册一个监听器:

x.registerListener(function(val) {
  alert("Someone changed the value of x.a to " + val);
});

因此,每当x.a的值发生变化时,监听器函数就会被触发。运行下面的代码行将弹出警告:

x.a = 42;

请看一个例子:https://jsfiddle.net/5o1wf1bn/1/

您还可以使用一个侦听器数组,而不是单个侦听器插槽,但是我想给您一个最简单的示例。

不是直接的:你需要一个“addListener/removeListener”接口的一对getter/setter…或者一个NPAPI插件(但这完全是另一个故事)。