1

I'm running the following code in Chrome and I'm a little confused as to why oldCurrent seems to reference currentStats.

I create a new object called oldCurrent and use jQuery.extend to copy the properties of the currentStats object. Then I attempt to copy the new data into currentStats object, to overwrite it with the properties of the new statsReport.audio property, also with jQuery.extend.

If I stop the debugger at this point, I can see that all of a sudden oldCurrent has all of the values that currentStats has, even though currentStats was written to after I copied into oldCurrent.

If jQuery.extend() is making a deep copy of the currentStats object, then why would oldCurrent suddenly contain all those values, as if it were a reference to currentStats?

The peer object is created from createPeerConn( ). The statsReport data could be any object. I know that the audio and video properties exist in statsData and are correct.

function createPeerConn() {

    var peer = {
        conn: null, 
        remotePeerID: "",
        statsIntervalID: -1,
        stats: {
            count: 0,
            prev: createStatsObj(),
            current: createStatsObj(),
            delta: createStatsObj()
        },
    };

    return peer;
}

function StreamStats()
{
    this.bytesSent = 0;
    this.packetsLost = 0;
    return this;
}


function createStatsObj()
{
    var a = new StreamStats();
    var v = new StreamStats();
    return { audio: a, video: v };
}


if ( statsReport ) {

    // 0. Copy the existing current values from the stats because we need to update 
    // the previous stats to the existing current.
    var currentStats = peer.stats.current;
    var oldCurrent = $.extend(true, {}, currentStats);

    // 1. Copy the current stats to the current object.
    // console.log("updateStats: peer: %o statsReport: %o", peer, statsReport);
    $.extend(true, currentStats.audio, statsReport.audio);
    $.extend(true, currentStats.video, statsReport.video);

    if ( currentStats.audio.bytesSent != statsReport.audio.bytesSent || currentStats.audio.packetsLost != statsReport.audio.packetsLost ) {
        console.log("bytesSent is not equal. %s, %s", currentStats.audio.bytesSent, statsReport.audio.bytesSent);
        console.log("packetsLost is not equal copy: %s original: %s", currentStats.audio.packetsLost, statsReport.audio.packetsLost);
    } else {
        console.log("equal: bytesSent copy: %s original: %s", currentStats.audio.bytesSent, statsReport.audio.bytesSent);
        console.log("equal: packetsLost copy: %s original: %s", currentStats.audio.packetsLost, statsReport.audio.packetsLost);
    }

    // 3. Crunch the deltas.
    var prevStats = peer.stats.prev;
    var delta = peer.stats.delta;
    delta.audio.bytesSent = currentStats.audio.bytesSent - prevStats.audio.bytesSent;

    // 4. Update the previous stats to what current was before it was overwritten.
    prevStats = oldCurrent;
}
Joey Carson
  • 2,973
  • 7
  • 36
  • 60
  • Can you add the initial values of the variables to your example, so we can test this out? – Barmar Apr 25 '15 at 06:29
  • I've updated how the objects are created in order to show their structure. As for where the other data comes from in statsReport, that would require far too much code. – Joey Carson Apr 25 '15 at 06:38
  • We just need enough detail so we can try to reproduce the problem you're having. – Barmar Apr 25 '15 at 06:44
  • 1
    `$.extend` does not do a deep copy of objects with constructors. See the duplicate question for more details. – Barmar Apr 25 '15 at 07:04
  • Interesting, I never would have guessed... This sounds like something that should be made obvious in the doc for jQuery.extend. For instance, the doc says the following: "Properties that are an object constructed via new MyCustomObject(args), or built-in JavaScript types such as Date or RegExp, are not re-constructed and will appear as plain Objects in the resulting object or array." This sounds like the returned object would just be a plain object (e.g. not run through a constructor) but all properties would be copies, e.g. if they were strings I'd expect copied strings not references. – Joey Carson Apr 25 '15 at 17:36
  • Yes, that's how I would have interpreted the doc. – Barmar Apr 25 '15 at 17:42
  • the more you get into javascript, the less you know... – Miguel Aug 19 '16 at 10:02

0 Answers0