简体   繁体   中英

Detecting if an object is changed in javascript

I have a function that is called every 1 second.

var latestObject; //this updated separately, it depends on user input so it may not be different every second
var previousObject;
function Tick(object) {
    if (latestObject !== previousObject) { //Problem is here
        previousObject = latestObject; //or here
        //do stuff with latestObject;
    }
}

However when latestObject is updated it's properties are changed, the variable is not set to a different object. So previousObject and latestObject are always equal and the do stuff never happens.

I could do:

function Tick(object) {
    var latestObjectString = JSON.stringify(latestObject);
    if (latestObjectString !== previousObject) { //Problem is here
        previousObject = latestObjectString; //or here
        //do stuff with latestObject;
    }
}

But then I'm doing JSON.stringify once every second, this seems inefficient, especially as latestObject is quite big, and quite deep.

Wouldn't it be better set previousObject to be a copy of latestObject, so that when properties on latestObject are changed, previousObject stays the same, and then this only happens when the objects are different which is less often than every second? But wouldn't there be a problem as copyOfObject == Object would never be true?

(the object is mostly properties, but has a few functions that don't ever change).

(No jQuery)

Description of the problem

The problem here is indeed related to the fact, that the same object is assigned to two different variables. Even if you change it in one place, the other changes it also.

This example shows you what really happens (jsFiddle: http://jsfiddle.net/tadeck/4hFC2/ ):

var objA = {'a':10, 'b': 20};
var objB = objA; // same instance assigned to both names
objB.a = 30; // instance is modified, its "a" property is changed
// now, both objA.a and objB.a show "30", as objA and objB is the same instance

However, having two different objects is not so ideal either, as comparing them is non-trivial (proof here: http://jsfiddle.net/tadeck/GN2m4/ ).

Solution no. 1. for comparing the objects

To solve this problem:

  1. You need to use two different objects (eg. by using some solution similar to jQuery's .extend() to construct new object from existing object). You currently achieve that part using unnecessary serialization.
  2. You need to compare them in a little more complex way (pretty universal solution for that is here: https://stackoverflow.com/a/1144249/548696 ).

In comparison to this, your solution may look less complex (at least in terms of code). I suggest using some JS performance tests to find out, which is more reasonable. JSON.stringify() is not always natively supported, so it may be doing things similarly complex (and resource-consuming), as the alternative solution I mentioned.

Solution no. 2. for solving the overall issue of detecting the changes

The other option is to rebuild your script and use eg. flags for marking the object as changed by user input. That would save you the processing of whole objects each second and may result in large efficiency gains.

The things you need to do in this case, are:

  1. In your user-input handlers set the flag whenever user changes some part of the object,
  2. Optionally, you could first compare the specific value with the original object (if user has changed it quickly and then reverted the change, just mark the value as not changed),
  3. To limit the processing of the changed object, you could even mark, which properties were changed (so you process only these properties, nothing else),

To achieve part of this solution, you could even use JavaScript setters and getters, as described by John Resig .

But, as I mentioned, it may require rebuilding your script (which we haven't seen, so we cannot say if it is necessary or it can be applied rather easily).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM