web-dev-qa-db-ja.com

toStringをカスタマイズするための推奨される方法は何ですか? Symbol.toStringTagを使用しますか、それともtoStringをオーバーライドしますか?

何を実装するか混乱しています。まず、モジュールでBabelを使用するため、ES6機能の実装に問題はありません。次に、class構造を使用して、古いプロトタイプメソッドではなくクラスを作成します。だから今、toStringをオーバーライドするのか(これは古い方法です)、このMDNドキュメントが言っているようにSymbol.toStringTagを実装するのか混乱しています https://developer.mozilla.org/en -US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toStringTag では、推奨される方法は何ですか?

12
Richeve Bebedor

それらは完全に異なるもののためのものです。

オブジェクトの文字列バージョンを定義しようとしている場合は、toStringメソッドを提供します。

Object.prototype.toStringがその"[object XYZ]"文字列を構築するために使用する情報をクラスに追加しようとしている場合は、名前がSymbol.toStringTagの値であるメソッドを提供します。

違いの図を次に示します。

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]

そのget [Symbol.toStringTag]を指定しなかった場合、その最後の行は"[object Object]"ではなく"[object Example]"を出力します。

ゲッターになることは持っていないことに注意してください。代わりにデータプロパティにすることができます。 Babelを使用しているので、 Public Class Fields support(現在はステージ2)を含めると、次のように定義できます。

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

...もちろんそれは書き込み可能ですが。代わりに:

class Example {
    constructor(x) {
        this.x = x;
    }
    toString() {
        return `Example[x=${this.x}]`;
    }
}
Object.defineProperty(Example.prototype, Symbol.toStringTag, {
    value: "Example"
});
23
T.J. Crowder