Skip to content

Readable JavaScript Values

One problem with JavaScript development is that the string representation of a value doesn’t tell you much about the value. For example, [null], [undefined], and '' all display as the empty string. [1,2}, [[1,2]], and [[1],[2]] all display as 1,2 (and so does "1,2"). And ({a: 1}), ({b: 2}), and new MySwankyNewObject() all display as [object Object].

If you use an IDE for development, this may not be a problem. Probably the IDE has its own string representation; even if it doesn’t, you can generally drill into objects by clicking on them. This doesn’t help those us of who prefer REPL development or printf-style debugging. When you display a debugging value (to the browser status line, to the alert() dialog, or to the Rhino console), you’d like some indication of what it actually is. And JavaScript doesn’t generally tell you, at least when the value is more complex than a string, number, or boolean.

Hence, readable.js. Readable adds a Readable class that can stringify a JavaScript value readably, for debugging purposes. Readable.toReadable([1,'', null, [3, 4]]) evaluates to [1, '', null, [3, 4]], not 1,,,3,4. And so on.

To make it easier to use the Readable class, Readable comes with a couple of hooks. First of all, it defines defines info, warn, error, and debug functions1 that display their arguments to the user. In Rhino, these functions call through to print. In a browser, they use alert() — unless fvlogger has been loaded first, in which case they use it instead[]. You can also replace Readable.log(level, message) or
Readable.display(message) to add your own behavior; for example,
to display the message in the status line, or AJAX it up to the server.

Secondly, Readable can add toString methods to Array.prototype and Object.prototype. Do this, and evaluating an expression in Rhino writes a readable representation to the console, without your having to wrap it in info(<var>...</var>) or Readable.toString(<var>...</var>). Doing this has the consequence that iterating over the properties of an Object or Array will yield an extra one (toString), so this is off by default. But define READABLE_REPLACE_TOSTRING before loading the file, or invoke Readable.replaceToString() after loading it, and you’ll get this behavior.

Files:
* readable.js
* documentation

Update: Fixed for Internet Explorer.


1 The reason there’s more than one function is that this is intended to be consistent with fvlogger. It’s also handy to be able to search your sources for one logging function, and not the other.

2 One advantage of including Readable even if you’re already using fvlogger is that now info([1,2]) prints something different from info([[1],[2]]). Another is that Readable extends the fvlogger functions with variadicity: info(key, '->', value) works now. (Without Readable, it’s equivalent to info(key), except that value is also evaluated for effect.) Finally, you can use Readable to extend Rhino with the same logging API. I use this to write modules — such as paths and beziers — that I test with Rhino and integrate into a UI in the browser.

6 Comments

  1. Asger Ottar Alstrup wrote:

    How does this compare to JSON?

    Wednesday, March 8, 2006 at 7:22 am | Permalink
  2. Oliver wrote:

    Good question. In brief, JSON output is intended for consumption by computers and by libraries written in other languages, and Readable output is intended for humans. This has all sorts of repercussions such as whether RegExps, null, undefined, and NaN are represented; whether representations can be limited in length or depth, and so on. For a longer answer, see the bottom of the docs http://osteele.com/sources/javascript/docs/readable, where I’ve just added a list of differences.

    Wednesday, March 8, 2006 at 9:09 pm | Permalink
  3. Rick Thomas wrote:

    Thanks, Oliver.
    This is a much needed tool that saved the day today and I’m sure on many future days.
    Good work! Now to spread the word.

    Wednesday, May 24, 2006 at 11:58 pm | Permalink
  4. Thanks Oliver. This is very handy.

    I’m starting to code thicker clients with javascript and I’ve been looking for cool debugging tools like this.

    Is it okay if I try merging this with jquery.debug?
    http://jquery.glyphix.com/

    Also, I believe the first check for null and undefined in Readable.toReadable(value,options) should return a “new String(value)” and not “String(value)”.

    Thursday, September 20, 2007 at 1:11 pm | Permalink
  5. Nope, not sure what i was witnessing, but new String(value) is wrong too. String(value) is now working for me. Readable.toReadable(null) returns a string now

    Thursday, September 20, 2007 at 1:25 pm | Permalink
  6. I think your constructor checks in Readable.toReadable(value,options) for Regexp, String etc should also include Date to use the native toString() date stringifier.

    Thursday, September 27, 2007 at 9:11 am | Permalink