Is there a way in JavaScript to have something like an event that listens to changes in a variable? so when its value is modified the event triggers and then 开发者_StackOverflow社区I can call a function. To put this more into context I have a function which handles the html rendering of an array of objects, and I want that function to be called automatically every time the array is modified.
Thanks.
Use object.watch
docs and if it is not supported natively look at this implementation: Object.watch() for all browsers?
I don't think what you ask is possible.
A solution might be to :
- encapsulate your data into a specific object
- access that data using a setter method of that object
- have that setter method both :
- set the data
- call your function
But it'll require you to rewrite a bit of your code.
It is possible now using Proxy object, see the demo in my answer to similar issue here.
It is possible to create Proxy for array, see the snippet below. In your case, just replace the console.log with your DOM modifying methods. Be careful though: adding a value to array modifies the array length which can invoke the proxy multiple times and modifying the array with it's methods like push()
can have other side effects to call the Proxy even more. It depends on UA implementation, but at least one Proxy call per modification should be guaranteed.
const ProxyArr = (arr, fn) => new Proxy(arr, {
get: (arr, key) => arr[key],
set: (arr, key, val) => fn(arr[key] = val, key, arr) || 1
});
// listen to array changes
let handler = (v, k, a) => console.log(`setting ${v} at ${k} (${a.length} items)`);
let arr = [];
let proxy = ProxyArr(arr, handler);
// test (see the console output)
proxy[0] = "aa";
proxy.push("bb");
console.log(arr);
console.log(proxy);
You could use setInterval
to check for its value so many times a second, and save it into a separate variable. You can check each time whether the real variable is different from the other one. In that case, call the function.
It's a dirty trick, though.
In ECMAScript 5 there are getter/setter properties... Read here: http://ejohn.org/blog/ecmascript-5-objects-and-properties/
Non-IE browsers support something similar:
http://robertnyman.com/2009/05/28/getters-and-setters-with-javascript-code-samples-and-demos/
For IE, you'll have to wait for IE9, or use only DOM-bases getters/setters.
Because JavaScript doesn't universally support setter/getter methods yet, I'd recommend you think about how you set your variables. One technique that would work is:
Array.prototype.setMember = function(index,newValue) {
alert("I will perform some action here");
this[index] = newValue;
}
var myArray = [1,2,3];
// x[0] = 11; // Don't do this any more
x.setMember(0,11);
alert(x[0]);
I'm personally not a huge fan of adding new methods to base prototypes, but it makes things easier to refactor in the short term.
I personally prefer to not use proxy and instead use EventEmitter. It would work something like this.
import { EventEmitter } from "events";
const testChangeEvent = new EventEmitter();
function changeTest(newVal){
test = newVal
testChangeEvent.emit("change")
}
let test = "val" // variable we want to listen for
and now every time we call changeTest() we can detect it and run code with
testChangeEvent.on("change", () => {
console.log("Code that is being called")
})
I'm 99% sure you can make it look a lot better and a lot more idiot-proof with getters and setters but this should be enough for small projects if your project is a commercial thought look into it please don't mack people debug for hours.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get
精彩评论