Is it possible to override JavaScript's toString() function to provide meaningful output for debugging?

Solution 1:

You can override toString in Javascript as well. See example:

function Foo() {}

// toString override added to prototype of Foo class
Foo.prototype.toString = function() {
  return "[object Foo]";
}

var f = new Foo();
console.log("" + f); // console displays [object Foo]

See this discussion on how to determine object type name in JavaScript.

Solution 2:

First override toString for your object or the prototype:

var Foo = function(){};
Foo.prototype.toString = function(){return 'Pity the Foo';};

var foo = new Foo();

Then convert to string to see the string representation of the object:

//using JS implicit type conversion
console.log('' + foo);

If you don't like the extra typing, you can create a function that logs string representations of its arguments to the console:

var puts = function(){
    var strings = Array.prototype.map.call(arguments, function(obj){
        return '' + obj;
    });
    console.log.apply(console, strings);
};

Usage:

puts(foo)  //logs 'Pity the Foo'

puts(foo, [1,2,3], {a: 2}) //logs 'Pity the Foo 1,2,3 [object Object]'

Update

E2015 provides much nicer syntax for this stuff, but you'll have to use a transpiler like Babel:

// override `toString`
class Foo {
  toString(){
    return 'Pity the Foo';
  }
}

const foo = new Foo();

// utility function for printing objects using their `toString` methods
const puts = (...any) => console.log(...any.map(String));

puts(foo); // logs 'Pity the Foo'

Solution 3:

If you are using Node it might be worth considering util.inspect.

var util = require('util')

const Point = {
  x: 1,
  y: 2,
  [util.inspect.custom]: function(depth) { return `{ #Point ${this.x},${this.y} }` }

}

console.log( Point );

This will yield:

{ #Point 1,2 }

While the version without inspect prints:

{ x: 1, y: 2 }

More information (+ an example for using in classes):

https://nodejs.org/api/util.html#util_util_inspect_custom

Solution 4:

An easy way to get debuggable output in browser JS is to just serialize the object to JSON. So you could make a call like

console.log ("Blah: " + JSON.stringify(object));

So for an example, alert("Blah! " + JSON.stringify({key: "value"})); produces an alert with the text Blah! {"key":"value"}

Solution 5:

With template literals:

class Foo {
  toString() {
     return 'I am foo';
  }
}

const foo = new Foo();
console.log(`${foo}`); // 'I am foo'