Geek Stuff: Debugging JS Arrays

While I can be a glutton for punishment, verifying Javascript arrays can be more than I want to deal with. If you print an array:

<script type="text/javascript">
var testarray = new Array(
    new Array(1, 2, 3, new Array(4, 5)),
    new Array(6, 7, 8, new Array(9, 10)),
    new Array(1, 2)
);

alert(testarray);
</script>

This creates a popup that says "1,2,3,4,5,6,7,8,9,10,1,2." In order to test for items in the sub-arrays, the quick and dirty method would involve typing commands into the browser's address bar:

javascript:alert(testarray[0])

This would pop up with "1,2,3,4,5." Firebug can help significantly with its DOM tab and JavaScript console. Still, I have found myself wanting a function similar to PHP's print_r() while changing global arrays in functions. Here is my little hack:

Array.prototype.pretty = function(spacer, prefix) {
    var first = true, afterarray = false, type, ret = '', x;

    if (spacer == undefined) {
        spacer = '';
    }
    if (prefix == undefined) {
        prefix = '';
    } else {
        prefix += ' => ';
    }

    ret += spacer+prefix+'Array(';
    for (x in this) {
        // Don't show this function prototype... or any others.
        type = typeof(ret[x]);
        if ((type != 'string') && (type != 'number') && (type != 'boolean')) {
            continue;
        }

        // Don't place commas before the first item.
        if (first) {
            first = false;
        } else {
            // If we are following an array with an array, don't add a newline
            if (this[x] instanceof Array) {
                afterarray = false;
            }
            // Place a newline after child arrays
            ret += ','+(afterarray ? "\n" : ' ');
            afterarray = false;
        }

        // Call ourselves recursively when an array is encountered.
        if (this[x] instanceof Array) {
            ret += "\n"+this[x].pretty(spacer+'    ', x);
            afterarray = true;
        } else {
            ret += this[x];
        }
    }

    // Close arrays
    ret += (afterarray ? "\n"+spacer : '')+')';

    return ret;
}

Now you can use:

<script type="text/javascript">
var testarray = new Array(
    new Array(1, 2, 3, new Array(4, 5)),
    new Array(6, 7, 8, new Array(9, 10)),
    new Array(1, 2)
);

alert(testarray.pretty());
</script>

Which will create:

Array(
    0 => Array(1, 2, 3,
        3 => Array(4, 5)
    ),
    1 => Array(6, 7, 8,
        3 => Array(9, 10)
    ),
    2 => Array(1, 2)
)

Arrays will be indented to an infinite depth so that more than three levels can be displayed. I specifically needed this for a situation that involved three-dimensional arrays.

Drawback: If you are using "for (var x in testarray)," this function prototype will appear as one of the 'x' items. You will either have to convert this to a standard function or check the datatype of 'x.'

Happy debugging.