Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

People also ask

What happen if we override toString () method?

We can override the toString() method in our class to print proper output. For example, in the following code toString() is overridden to print the “Real + i Imag” form.

Can toString be override?

Override the toString() method in a Java Class A string representation of an object can be obtained using the toString() method in Java. This method is overridden so that the object values can be returned.

Can we override toString method in Javascript?

While not as common, the method can be invoked directly (for example, myObject. toString() ). This method is inherited by every object descended from Object , but can be overridden by descendant objects (for example, Number. prototype.

Why do we override toString?

By overriding the toString( ) method, we are customizing the string representation of the object rather than just printing the default implementation. We can get our desired output depending on the implementation, and the object values can be returned.


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.


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'

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


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"}


With template literals:

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

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

Add the 'Symbol.toStringTag' property to the custom object or class.

The string value which is assigned to it will be its default string description because it is accessed internally by the Object.prototype.toString() method.

For example:

class Person {
  constructor(name) {
    this.name = name
  }
  get [Symbol.toStringTag]() {
    return 'Person';
  }
}

let p = new Person('Dan');
Object.prototype.toString.call(p); // [object Person]

class Person {
  constructor(name) {
    this.name = name
  }
  get[Symbol.toStringTag]() {
    return 'Person';
  }
}

let p = new Person('Dan');
console.log(Object.prototype.toString.call(p));

Some Javascript types such as Maps and Promises have a built-in toStringTag symbol defined

Object.prototype.toString.call(new Map());       // "[object Map]"
Object.prototype.toString.call(Promise.resolve()); // "[object Promise]"

Because Symbol.toStringTag is a well-known symbol, we can reference it and verify that the above types do have the Symbol.toStringTag property -

new Map()[Symbol.toStringTag] // 'Map'
Promise.resolve()[Symbol.toStringTag] // 'Promise'

Just override the toString() method.

Simple example:

var x = {foo: 1, bar: true, baz: 'quux'};
x.toString(); // returns "[object Object]"
x.toString = function () {
    var s = [];
    for (var k in this) {
        if (this.hasOwnProperty(k)) s.push(k + ':' + this[k]);
    }
    return '{' + s.join() + '}';
};
x.toString(); // returns something more useful

It does even better when you define a new type:

function X()
{
    this.foo = 1;
    this.bar = true;
    this.baz = 'quux';
}

X.prototype.toString = /* same function as before */

new X().toString(); // returns "{foo:1,bar:true,baz:quux}"