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


当前回答

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

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

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

https://github.com/jarederaj/jQueue

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

其他回答

No.

但是,如果这真的很重要,你有两个选择(第一个是测试,第二个不是):

首先,使用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);
}

其次,你可以把手表的价值:

给定上面的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);

在getter和setter的帮助下,您可以定义一个JavaScript类来做这样的事情。

首先,我们定义一个名为MonitoredVariable的类:

class MonitoredVariable {
  constructor(initialValue) {
    this._innerValue = initialValue;
    this.beforeSet = (newValue, oldValue) => {};
    this.beforeChange = (newValue, oldValue) => {};
    this.afterChange = (newValue, oldValue) => {};
    this.afterSet = (newValue, oldValue) => {};
  }

  set val(newValue) {
    const oldValue = this._innerValue;
    // newValue, oldValue may be the same
    this.beforeSet(newValue, oldValue);
    if (oldValue !== newValue) {
      this.beforeChange(newValue, oldValue);
      this._innerValue = newValue;
      this.afterChange(newValue, oldValue);
    }
    // newValue, oldValue may be the same
    this.afterSet(newValue, oldValue);
  }

  get val() {
    return this._innerValue;
  }
}

假设我们想监听钱的变化,让我们创建一个初始值为0的MonitoredVariable实例:

const money = new MonitoredVariable(0);

然后我们可以使用money来获取或设置它的值。

console.log(money.val); // Get its value
money.val = 2; // Set its value

因为我们没有为它定义任何监听器,所以在钱之后没有什么特别的事情发生。Val变成了2。

现在让我们定义一些侦听器。我们有四个可用的侦听器:beforeSet、beforeChange、afterChange、afterSet。 当你使用金钱时,下面的事情会依次发生。val = newValue更改变量的值:

钱。beforeSet (newValue oldValue); 钱。beforeChange (newValue oldValue);(如果它的值没有改变,将被跳过) 钱。val = newValue; 钱。afterChange (newValue oldValue);(如果它的值没有改变,将被跳过) 钱。afterSet (newValue oldValue);

现在我们定义了afterChange监听器,它只会在金钱之后被触发。val已经改变(而afterSet将被触发,即使新值与旧值相同):

money.afterChange = (newValue, oldValue) => {
  console.log(`Money has been changed from ${oldValue} to ${newValue}`);
};

现在设置一个新的值3,看看会发生什么:

money.val = 3;

您将在控制台中看到以下内容:

Money has been changed from 2 to 3

完整代码请参见https://gist.github.com/yusanshi/65745acd23c8587236c50e54f25731ab。

这是一个老线程,但我在使用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);
}

现在每次单击子按钮时都会更新非父按钮。工作stackblitz

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]);}
                    });
            }

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