Comparing window State Over Time

Javascript's window object is definitely one of those "LOL SO RANDUM XD" instances that make developing in javascript so fun. Nominally, it represents the current state of the browser window. However, it also uniquely contains all global javascript variables, objects, and functions related to the current session. Along with the document object. And speech related functionality. It's a mess. I probably designed it.

Recently I was trying to debug an extension issue with scrolling and wanted to compare the scrollY member over time. Logic would tell us this would be easy:

var old_window_state = window;
//scroll the window
console.log( "old: " + old_window_state.scrollY + ", current: " + window.scrollY );

But logic would be wrong.

In Javascript, = is overloaded. For primitives, it copies by value:

var a = 5;
var b = a;
a = 7;
//b = 5

But for objects, it copies by reference. For example:

var a = { 'member1' : 5 }
b = a
a.member1 = 7
//b = { 'member1' : 7 }

So cool, we are going to have to deal with that. We can either use jQuery's extend method to make a deep-copy:

var old_window_state = $.extend( true, {}, window );

or we can use the new Object.assign method in EMCA6:

var old_window_state = Object.assign( {}, window ); 

Caveat: Object.assign will not properly clone references in the object. To do that, you would need to use a recursive solution.

So let's write a small package to handle comparisons for us:

var window_states = [];

function take_snapshot( ) {
    var temp_state = Object.assign( {}, window )
    window_states.push( temp_state );
}

function compare_snapshots( ) {
    for( var item in window ) { 
        for( var i = 0; i < window_states.length; i++ ) {
            if( window_states[ i ][ item ] != window[ item ] && window_states[ i ][ item ] != undefined ) { 
                console.log( item + ", previous: " + window_states[ i ][ item ] + ", current: " + window[ item ] ); 
            } 
        }
    }
}

That took longer than it had to.