当某个变量的值发生变化时,是否有可能在 JS 中触发一个事件?接受 JQuery。
监听 JavaScript 中的变量变化
这个问题最初发布于 2009 年,现有的大多数答案要么过时、无效,要么需要包含大型臃肿的库:
- Object.watch和Object.observe都已弃用,不应使用。
 - onPropertyChange是一个 DOM 元素事件处理程序,仅适用于某些版本的 IE。
 - Object.defineProperty允许您使对象属性不可变,这将允许您检测尝试的更改,但它也会阻止任何更改。
 - 定义 setter 和 getter 是有效的,但它需要大量的设置代码,并且在您需要删除或创建新属性时效果不佳。
 
从 2018 年开始,您现在可以使用Proxy对象来监视(和拦截)对对象所做的更改。它是专为 OP 尝试做的事情而构建的。这是一个基本示例:
var targetObj = {};
var targetProxy = new Proxy(targetObj, {
  set: function (target, key, value) {
      console.log(`${key} set to ${value}`);
      target[key] = value;
      return true;
  }
});
targetProxy.hello_world = "test"; // console: 'hello_world set to test'
该Proxy对象的唯一缺点是:
- 该
Proxy对象在旧浏览器(例如 IE11)中不可用,并且polyfill无法完全复制Proxy功能。 - 代理对象在处理特殊对象(例如,
Date)时并不总是像预期的那样——Proxy对象最好与普通对象或数组配对。 
如果您需要观察对嵌套对象所做的更改,则需要使用专门的库,例如Observable Slim (我已发布)。它是这样工作的:
var test = {testing:{}};
var p = ObservableSlim.create(test, true, function(changes) {
    console.log(JSON.stringify(changes));
});
p.testing.blah = 42; // console:  [{"type":"add","target":{"blah":42},"property":"blah","newValue":42,"currentPath":"testing.blah",jsonPointer:"/testing/blah","proxy":{"blah":42}}]
 
是的,这现在完全有可能!
我知道这是一个旧线程,但现在使用访问器(getter 和 setter)可以实现这种效果:https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects#Defining_getters_and_setters
您可以像这样定义一个对象,其中aInternal表示字段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/
您还可以使用一组侦听器而不是单个侦听器槽,但我想给您提供一个最简单的示例。
不。
但是,如果真的那么重要,您有两个选择(第一个经过测试,第二个没有):
首先,使用 setter 和 getter,如下所示:
var myobj = {a : 1};
function create_gets_sets(obj) { // make this a framework/global function
    var proxy = {}
    for ( var i in obj ) {
        if (obj.hasOwnProperty(i)) {
            var k = i;
            proxy["set_"+i] = function (val) { this[k] = val; };
            proxy["get_"+i] = function ()    { return this[k]; };
        }
    }
    for (var i in proxy) {
        if (proxy.hasOwnProperty(i)) {
            obj[i] = proxy[i];
        }
    }
}
create_gets_sets(myobj);
那么你可以做这样的事情:
function listen_to(obj, prop, handler) {
    var current_setter = obj["set_" + prop];
    var old_val = obj["get_" + prop]();
    obj["set_" + prop] = function(val) { current_setter.apply(obj, [old_val, val]); handler(val));
}
然后将侦听器设置为:
listen_to(myobj, "a", function(oldval, newval) {
    alert("old : " + oldval + " new : " + newval);
}
其次,您可以关注value:
鉴于上面的 myobj ,上面有“a”:
function watch(obj, prop, handler) { // make this a framework/global function
    var currval = obj[prop];
    function callback() {
        if (obj[prop] != currval) {
            var temp = currval;
            currval = obj[prop];
            handler(temp, currval);
        }
    }
    return callback;
}
var myhandler = function (oldval, newval) {
    //do something
};
var intervalH = setInterval(watch(myobj, "a", myhandler), 100);
myobj.set_a(2);
使用Prototype:https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
// Console
function print(t) {
  var c = document.getElementById('console');
  c.innerHTML = c.innerHTML + '<br />' + t;
}
// Demo
var myVar = 123;
Object.defineProperty(this, 'varWatch', {
  get: function () { return myVar; },
  set: function (v) {
    myVar = v;
    print('Value changed! New value: ' + v);
  }
});
print(varWatch);
varWatch = 456;
print(varWatch);
<pre id="console">
</pre>
其他例子
// Console
function print(t) {
  var c = document.getElementById('console');
  c.innerHTML = c.innerHTML + '<br />' + t;
}
// Demo
var varw = (function (context) {
  return function (varName, varValue) {
    var value = varValue;
  
    Object.defineProperty(context, varName, {
      get: function () { return value; },
      set: function (v) {
        value = v;
        print('Value changed! New value: ' + value);
      }
    });
  };
})(window);
varw('varWatch'); // Declare
print(varWatch);
varWatch = 456;
print(varWatch);
print('---');
varw('otherVarWatch', 123); // Declare with initial value
print(otherVarWatch);
otherVarWatch = 789;
print(otherVarWatch);
<pre id="console">
</pre>
很抱歉提出一个旧线程,但这里有一个小手册,适用于那些(像我一样!)不了解 Eli Grey 示例如何工作的人:
var test = new Object();
test.watch("elem", function(prop,oldval,newval){
    //Your code
    return newval;
});
希望这可以帮助某人