Super Powerful Debugging Function in Javascript

Super powerful debugging function in JavaScript. This function will output your variable in question to the Firebug console or the HTML page. With it you can debug anything from an Object, array, string, integer, etc. It is also recursive-safe.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/**
 * @author: Ronald Pringadi, 2011
 * @desc: to debug a JavaScript Object
 * @usage: debug(yourObject);  
 * or debug(yourString);
 * or debug(yourArray);  
 * @param object vTraceObject
 * @param string vPadding
 * @param object vPadding
 *
 */


function debug(vTraceObject, vPadding, vPreviousTraceObject) {
    'use strict';

    function getObjectClass(vObj) {

        if (vObj && vObj.constructor && vObj.constructor.toString) {
            var arr = vObj.constructor.toString().match(/function\s*(\w+)/);
            if (arr && arr.length === 2) {
                return arr[1];
            }
        }
        return undefined;
    }
    function typeOf(vObj) {

        var vResult = typeof vObj;
        if (vResult === 'object') {
            try {
                if (vObj.length !== undefined) {
                    vResult = 'array';
                }
            } catch (e) {
            }
        }

        return vResult;
    }  
    function print(vPadding, vType, vValue) {

        if (vPadding === undefined) {
            vPadding = '';
        }
        if (vType === undefined) {
            vType = '';
        }
        if (vValue === undefined) {
            vValue = '';
        }
        try{
            console.log(vPadding + ' (' + vType + '): ' + vValue + "\n");
        }catch(e){
            document.write(vPadding + ' (' + vType + '): ' + vValue + "\n");
        }
       
    }  

    if (vPadding === '' || vPadding === undefined) {
        vPadding = '';
    }
    if (typeOf(vTraceObject) === 'object'
            && typeOf(vPreviousTraceObject) === 'object') {
        if (getObjectClass(vPreviousTraceObject) === getObjectClass(vTraceObject)) {
            print(vPadding, 'ERROR', 'RECURSION EXISTING ...');
            return null;
        }
    }

    var vType = typeOf(vTraceObject);
    if (vType === 'object' || vType === 'array') {
        if (vPadding === '') {
            print(vPadding, vType, '...');
            vPadding = '----';

        }
        try {
            var vTempType = '';
            var variable = '';
            for (variable in vTraceObject) {
                vTempType = typeOf(vTraceObject[variable]);
                if (vTempType === 'object' || vTempType === 'array') {
                    print(vPadding, vTempType, variable);
                    debug(vTraceObject[variable], vPadding + '----',
                            vTraceObject);
                } else {
                    print(vPadding, vTempType, variable + ' : '
                            + vTraceObject[variable]);
                }
            }
        } catch (e) {
            print(vPadding, 'ERR', 'EXCEPTION');
        }
    } else {
        print(vPadding, vType, vTraceObject);

    }


}

function objA() {
    this.varA1 = 'a1';
    this.varA2 = 'a2';
    this.myCars = new Array();
    this.myCars[0] = "Saab";
    this.myCars[1] = "Volvo";
    this.myCars[2] = "BMW";
}

function objB() {
    this.varB1 = 'b1';
    this.varB2 = 'b2';
    this.varB3 = new objA;

}
instanceB = new objB;

Output:

1
2
3
4
5
6
7
8
9
10
(object): ...
---- (string): varB1 : b1
---- (string): varB2 : b2
---- (object): varB3
-------- (string): varA1 : a1
-------- (string): varA2 : a2
-------- (array): myCars
------------ (string): 0 : Saab
------------ (string): 1 : Volvo
------------ (string): 2 : BMW

A note from later — what the modern browser console gives you for free.

When this post was written, Firebug (the Firefox extension) was where serious JavaScript debugging happened, and a recursion-safe pretty-printer like the one above filled a real gap. Firebug was discontinued in 2017 once Firefox’s built-in DevTools caught up, and the modern browser console can do most of what this function does without any helper code. 🦊

A few one-liners that cover the common cases:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const car = { make: 'Saab', model: '900', year: 1995 };

// 1. Object shorthand — Chrome/Firefox/Safari all label the value with its name.
console.log({ car });
//   { car: { make: 'Saab', model: '900', year: 1995 } }

// 2. console.dir — walks the object as an interactive, expandable tree.
console.dir(car, { depth: null });

// 3. console.table — best when you have an array of similar objects.
console.table([
  { make: 'Saab', year: 1995 },
  { make: 'Volvo', year: 2001 },
  { make: 'BMW',   year: 2010 },
]);

// 4. JSON.stringify with indentation — copy-pasteable, great for logs and bug reports.
console.log(JSON.stringify(car, null, 2));

Each of those has its niche: { var } shorthand is what you reach for inside a function ten times a day, console.dir is for poking at DOM nodes and large objects interactively, console.table turns arrays into actual tables (a small everyday joy 🎉), and JSON.stringify(obj, null, 2) is what you want when the output needs to land in a file or a chat message.

One thing the modern console doesn’t automatically protect you from is circular references — JSON.stringify throws on them. If you need a copy-pasteable dump that survives cycles, you still need a helper. A modern, smaller version of the same idea as the original function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function safeStringify(obj, indent = 2) {
  const seen = new WeakSet();
  return JSON.stringify(obj, (key, value) => {
    if (typeof value === 'object' && value !== null) {
      if (seen.has(value)) return '[Circular]';
      seen.add(value);
    }
    return value;
  }, indent);
}

const a = { name: 'a' };
const b = { name: 'b', ref: a };
a.ref = b; // circular!

console.log(safeStringify(a));
// {
//   "name": "a",
//   "ref": {
//     "name": "b",
//     "ref": "[Circular]"
//   }
// }

So the original function is no longer the tool of choice in 2024+, but the idea behind it — “give me a recursion-safe, copy-pasteable dump of anything” — is just as useful today. The modern toolbox just hands you most of it in two lines instead of fifty. 🛠️

This entry was posted in javascript, Web Development. Bookmark the permalink.

Comments are closed.