在JavaScript中侦听可变更改

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

是的, object.watch (这是非标准的)。 这是我的实现在每个当前的主要浏览器。

没有。

但是,如果这真的很重要,你有两个select(第一个是testing,第二个不是):

首先,使用setters和getters,如下所示:

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

对不起,提出一个旧的线程,但这是谁(像我一样)的一个小手册,看不出Eli Gray的例子是如何工作的:

 var test = new Object(); test.watch("elem", function(prop,oldval,newval){ //Your code return newval; }); 

希望这可以帮助别人

是的,这是完全可能的!

我知道这是一个古老的线程,但现在这种效果是可能的使用访问器(getters和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 xa to " + val); }); 

所以无论什么时候改变xa的值,侦听器函数都会被触发。 运行下面的行将会popup警报:

 xa = 42; 

在这里看到一个例子: https : //jsfiddle.net/5o1wf1bn/1/

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

使用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> 

正如Luke Schafer的回答 ( 注意 :这是指他的原始文章;但是这里的整个观点在编辑之后仍然有效),我还会build议一对Get / Set方法来访问你的价值。

不过,我会build议一些修改(这就是为什么我张贴…)。

该代码的一个问题是对象myobj的字段a是可直接访问的,所以可以在不触发监听器的情况下访问它/更改它的值:

 var myobj = { a : 5, get_a : function() { return this.a;}, set_a : function(val) { this.a = val; }} /* add listeners ... */ myobj.a = 10; // no listeners called! 

封装

所以,为了保证听众实际上被叫,我们将不得不禁止直接进入该领域。 怎么做? 使用封闭

 var myobj = (function() { // Anonymous function to create scope. var a = 5; // 'a' is local to this function // and cannot be directly accessed from outside // this anonymous function's scope return { get_a : function() { return a; }, // These functions are closures: set_a : function(val) { a = val; } // they keep reference to // something ('a') that was on scope // where they were defined }; })(); 

现在你可以使用相同的方法来创build和添加Luke所提出的监听器,但是你可以放心,没有任何可能的方式来读或写a未被注意a事情!

以编程方式添加封装的字段

仍然在卢克的轨道上,我现在提出一个简单的方法来通过简单的函数调用来将封装字段和相应的getter / setter添加到对象。

请注意,这只适用于值types 。 为了与引用types一起工作,必须实施某种深层副本 (例如,参见这个 )。

 function addProperty(obj, name, initial) { var field = initial; obj["get_" + name] = function() { return field; } obj["set_" + name] = function(val) { field = val; } } 

这和以前一样:我们在一个函数上创build一个局部variables,然后我们创build一个闭包。

如何使用它? 简单:

 var myobj = {}; addProperty(myobj, "total", 0); window.alert(myobj.get_total() == 0); myobj.set_total(10); window.alert(myobj.get_total() == 10); 

AngularJS (我知道这不是JQuery ,但这可能会有所帮助。[纯JS在理论上是好的]):

 $scope.$watch('data', function(newValue) { .. 

其中“数据”是您的范围内的variables的名称。

有一个链接到文档。

如果您使用jQuery {UI}(每个人都应该使用:-)),则可以使用.change()和一个隐藏的<input />元素。

对于几年后的调整:

大多数浏览器(和IE6 +)的解决scheme都可以使用onpropertychange事件和更新的规范defineProperty。 小问题是你需要使你的variables成为一个dom对象。

全部细节:

http://johndyer.name/native-browser-get-set-properties-in-javascript/

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

您正在寻找的function可以通过使用“defineProperty()”方法来实现 – 只有现代浏览器才能使用:

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

如果您需要更多的跨浏览器支持,我写了一个jQuery扩展,它具有一些相似的function:

https://github.com/jarederaj/jQueue

处理排队callback的小jQuery扩展到variables,对象或键的存在。 您可以将任意数量的callback分配给可能受后台进程影响的任意数量的数据点。 jQueue监听和等待你指定的这些数据的存在,然后用它的参数发起正确的callback。

 //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); 

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

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

没有办法执行这个,只是需要编程规范…虽然你可以使用grep (或类似的东西)来检查你的代码没有直接设置globalVar的值。

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

再一次,这个派对我迟到了。 我知道这不是纯粹的JavaScript或jQuery; 然而,我已经在knockout.js中玩弄了一个项目,并且发现subscribe()方法对于事件的值发生改变时触发事件(或通知)很有效。 这是一个简单的例子:

 var foo = ko.observable(false); foo.subscribe(function () { console.log('`foo` has changed: ' + foo()); if (foo() === true) { // do something here } }); 

当然, subscribe()对于knockout的“observables”不适用于常规variables。 这里是链接到淘汰赛文件页面涵盖observables和订阅,感兴趣的人: http : //knockoutjs.com/documentation/observables.html

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