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

狂风中的少年 提交于 2019-11-30 09:22:00

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"
});
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!