Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the recommended way to customize toString? Using Symbol.toStringTag or overriding toString?

I'm confused on what to implement, first, my module will use Babel so there are no problems implementing ES6 features, second, I will use the class construct to create class and not the old prototypal method. So now, I'm confused if I'm going to override toString (which is the old way) or just implement Symbol.toStringTag like what this MDN documentation said, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toStringTag So what is the recommended way?

like image 498
Richeve Bebedor Avatar asked Mar 19 '17 13:03

Richeve Bebedor


People also ask

Why should you override the toString () method?

When you create a custom class or struct, you should override the ToString method in order to provide information about your type to client code. For information about how to use format strings and other types of custom formatting with the ToString method, see Formatting Types.

Do you need to override toString?

Expected output As you can see above, we can override the toString() method of the Student class to get a meaningful presentation of the object. In conclusion, it's a good idea to override toString() , as we get proper and customized output when an object is used.

What will happen if you will not override toString method?

So, whenever you use or print a reference variable of type in which toString() method is not overrided, you will get an output like above. You will not get what the object actually has in it. There will be no information about state or properties of an object.

Can toString method be overridden?

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.


1 Answers

They're for different things entirely.

If you're trying to define the string version of your object, provide a toString method.

If you're trying to add information to your class that Object.prototype.toString will use to build its "[object XYZ]" string, provide a method whose name is the value of Symbol.toStringTag.

Here's an illustration of the difference:

class Example {
    constructor(x) {
        this.x = x;
    }
    toString() {
        return `Example[x=${this.x}]`;
    }
    get [Symbol.toStringTag]() {
        return "Example";
    }
}
const e =  new Example(42);
console.log(e.toString());                      // Example[x=42]
console.log(String(e));                         // Example[x=42]
console.log(Object.prototype.toString.call(e)); // [object Example]

If we hadn't provided that get [Symbol.toStringTag], that last line would output "[object Object]" rather than "[object Example]".

Note that it doesn't have to be a getter, it can be a data property instead. Since you're using Babel, you could define it like this if you include Public Class Fields support (currently Stage 2):

class Example {
    constructor(x) {
        this.x = x;
    }
    toString() {
        return `Example[x=${this.x}]`;
    }
    [Symbol.toStringTag] = "Example";
}

...although of course it would be writable. Alternately:

class Example {
    constructor(x) {
        this.x = x;
    }
    toString() {
        return `Example[x=${this.x}]`;
    }
}
Object.defineProperty(Example.prototype, Symbol.toStringTag, {
    value: "Example"
});
like image 89
T.J. Crowder Avatar answered Sep 28 '22 22:09

T.J. Crowder