Object#toSourceが便利なんだけど、文字列がエスケープされたままだったりするので、関数で作ってみた
Firefoxでちょこっとチェックしただけです。五分ぐらいで適当に書いているのだけど、毎回毎回書くのは時間の無駄なので。
function toSource(obj, indent) { indent = indent || ""; if (obj === null) return indent + "null"; if (obj === void 0) return indent + "undefined"; if (obj.setTimeout) return indent + "[object Window]"; if (obj.nodeType === 9) return indent + "[object Document]"; if (obj.nodeType) return indent + "[object " + (obj.tagName || "") + " Node]"; var arr = [], type = Object.prototype.toString.call(obj), func = arguments.callee, next_indent = indent + (func.indent || "\t"); switch (type) { case "[object Boolean]": case "[object Number]": case "[object RegExp]": case "[object Date]": return indent + obj; case "[object String]": return indent + '"' + obj.replace(/"/g, '\\"').replace(/\r/g, "\\r").replace(/\n/g, "\\n") + '"'; case "[object Function]": return (indent + obj).replace(/\n/g, "\n" + indent); default: if (!("length" in obj)) { for (var i in obj) { arr.push( next_indent + func(i) + ": " + func(obj[i], next_indent).replace(/^\s+/g, "") ); } return indent + "{\n" + arr.join(",\n") + "\n" + indent + "}"; } case "[object NodeList]": case "[object HTMLCollection]": case "[object Arguments]": case "[object Array]": for (var i = 0, iz = obj.length; i < iz; ++i) arr.push( func(obj[i], next_indent).replace(/^\s* /g, next_indent) ); return indent + "[\n" + arr.join(",\n") + "\n" + indent + "]"; } }