JavaScriptingBuilding a JavaScript object browser

AS WE'VE SEEN in previous articles, JavaScript allows you to build and use objects in your client-side Web pages. These objects can be just as powerful and complex as those created in more traditional object-oriented languages. This complexity can lead to bugs that are incredibly difficult to track down and eliminate, simply because there are so few tools for debugging client-side JavaScript. (There are tools to be had, but they are usually dependent on one browser version or another or only work with one browser brand.) Fortunately, JavaScript is powerful enough that with a little work, you can build many of your own debugging tools.

One such tool is a simple JavaScript object browser. The basis of this tool is the JavaScript for/in statement. This statement allows you to execute a set of statements for each and every property of an object. For example, consider the code shown in Listing 1. This simple program will loop through the properties of the built-in navigator object and write the name of each property to the browser window. (If this doesn't seem like a useful thing to do, try loading this page into various Web browsers. You might be very surprised by what you see!)

Exposing an Object's Contents
We've seen how to expose the names of an object's properties, but how can we see the actual contents of each property? This is a little trickier than you might think, but it's still fairly easy to do.

As I said, when a property is exposed inside a for/in statement, all that's really exposed is the name of the property. So, all we have to work with is a string containing that name, with no indication of what that property actually contains. What we need is a way to turn that name string into an actual reference to the property itself. This is where the eval statement comes in handy. It lets us build a JavaScript statement using strings and then pass that string to the JavaScript interpreter for execution. Assuming that the string "appName" is in the variable part (as shown in Listing 1), we could code something such as:

eval("navAppName = navigator." + part);
After this statement executes, the variable navAppName will hold the actual contents of the navigator.appName property. We can then use this variable just as we would any other. (Note that some versions of Netscape Navigator will return an error if you try to declare a variable inside an eval statement. So, it's a good idea to declare navAppName (and assign it some dummy value] before executing the eval statement above.)

Determining a Property's Type
At this point, we can expose all of the properties of an object and view what's actually inside those properties. All that's left is to determine the type of each property's contents so that we can properly display those contents on screen. For this, we can use the typeof operator. (Note that this operator is only available in JavaScript v1.1 and later.) As the name implies, the typeof operator will tell us the type of the data contained in a variable or property.

Here again, we can't simply use the information obtained from the action of the for/in statement. For example, if we were to alter Listing 1 to include the statement: "alert(typeof part)" in our for/in loop, each and every alert window would contain the result "string" (because the part variable contains a string). So, we need to use an eval statement once again to determine the true type of each property. Going back to Listing 1, something such as this would work nicely:

eval( "partType  = typeof navigator." + part);
Once this has executed, the variable partType will contain one of the following literals: "string", "number", "boolean", "object", "function", or "undefined". We can then use this information to determine how to best display the value in the property. (As you might have noticed, there is no "array" type returned by the typeof operator. This is because, in JavaScript, arrays and objects are exactly the same thing. They just happen to be referenced differently.)

A Simple Object Browser

  • Listing 2 pulls all of this together to create a very simple JavaScript object browser. Most of the hard work is carried out in the showObjStructure function. This function accepts a string that names the object to dissect as well as a border thickness for the table that the results will be displayed in.

    The first step in the function is to create some local variables that will hold the contents of the object and its individual properties. Second, we use an eval statement to turn the name of our object into a reference to the object itself. Then, we begin building our result table and enter the for/in loop that will expose the properties of the object.

    Next, we need to build the fully qualified name of our property and extract it's contents. Because JavaScript makes no distinction between arrays and objects, this can be accomplished easily by putting the property name in quotes, and then putting that inside a set of square brackets. In other words, instead of having to code, we can code object['property']. To JavaScript, these are exactly the same thing. (Besides being simple, this approach allows us to examine properties with names that aren't valid JavaScript variable names. Array elements, for instance, can have numbers or arbitrary strings for names. For an example of such troublesome names, check out the contents of the navigator.plugins array.)

    After this is all done, it's a simple matter of determining the type of the property, and then outputting the appropriate HTML based on that type. If the property is a simple scalar value, we just print it out with an appropriate description. If the type is an object or array (and it isn't null), we include a link that will reload the page and pass this property/object to the showObjStructure function. This allows us to "drill down" into each object.

    Using the Object Browser
    Near the end of Listing 2, you'll notice a short block of JavaScript. The first few statements use the search property of the document object to determine which object to examine. For example, if you wanted to load the page and look at the navigator object, you would invoke the page like this:

    If you don't specify an object, the self object is loaded by default.

    The next few statements define a couple of simple JavaScript arrays. Try examining these with the object browser to see how you can easily drill down through the contents of an object.

    Finally, a document.write statement is used to invoke the showObjStructure function and display the contents of the specified object.

    Browser Differences
    One of the main uses for this simple object browser is to be able to dynamically view the differences between the Document Object Models of various Web browsers. While this object browser does work in both Navigator and Internet Explorer (IE), you'll notice right away that IE doesn't expose as many of its built-in objects to the for/in statement as Navigator does. For example, if you try to look at IE's navigator.plugins array, you'll get an error message. Unfortunately, there's really not much that can be done about this because IE simply doesn't let the for/in statement peek at the properties of this object. (If you want get rid of these error messages in IE, enclose the for/in loop in a try/catch block. Note that this will make the script incompatible with Navigator, which does not currently support try/catch error handling.)

    Another difference between browsers is that when looking at the self or window object, Navigator exposes all programmer-defined global variables, while IE does not. Another Navigator quirk is that variables declared inside functions are exposed as if they were global, unless you use the var keyword when you declare them. To see an example of this, remove the var keyword from any of the local variables defined in the showObjStructure function and then examine the self object. (Tip: Do not remove the var keyword from the declaration for the result variable; on second thought, give it a try and see what happens!)

    The only real drawback to this simple object browser is that it requires a page reload whenever you drill down to see the structure of another object. For complex objects with calculated values in them, this could have the nasty side effect of resetting them to their original state. However, this could be solved fairly easily by loading the object browser in one frame and the objects you want to examine in another.

    Got a Debugging Trick of Your Own?
    This object browser is one of my favorite JavaScript debugging tools. Given the lack of commercial JavaScript tools, I'm sure that many of you have come up with your own. So, let me know about yours and I'll try to feature it in an upcoming column.

  • About the Author

    Steven Disbrow is the owner of EGO Systems, a computer consulting firm in Chattanooga, TN. He can be contacted at [email protected].