TypeScript Symbol

Symbol は ES6 で導入されたプリミティブデータ型で、一意の識別子を表します。

TypeScript では、Symbol をオブジェクトのプロパティキーとして使用でき、プロパティの一意性を保証します。

これは、プライベートプロパティを作成したり、プロパティ名の衝突を避けたりする場面で非常に役立ちます。


SVG 図解:Symbol の動作原理背景 タイトル Symbol の特性Symbol の作成 Symbol() による作成 var sym1 = Symbol("key") var sym2 = Symbol("key") // sym1 !== sym2 作成のたびに一意 矢印 オブジェクトプロパティ オブジェクトのプロパティキーとして使用 var obj = { [sym]: "value" } // 一意のプロパティ名 矢印グローバル登録 Symbol.for() グローバルレジストリ 同じキー 等しい 下半分:組み込み Symbol 一般的な組み込み Symbol組み込み Symbol 1 Symbol.iterator - イテレータ組み込み Symbol 2 Symbol.toStringTag - オブジェクトの説明組み込み Symbol 3 Symbol.hasInstance - instanceof矢印マーク

なぜ Symbol が必要なのか

JavaScript では、オブジェクトのプロパティ名はすべて文字列であり、衝突が発生することがあります。

Symbol は一意の識別子を作成する方法を提供し、Symbol() を呼び出すたびに新しい一意の値が作成されます。

これは、プライベートプロパティの作成、一意の定数の定義、イテレータの実装などの場面で非常に役立ちます。

概念の説明:Symbol は JavaScript のプリミティブデータ型の一つで、Symbol() 関数によって作成されます。各 Symbol 値は一意であり、説明が同じでも等しくなりません。


Symbol の作成

Symbol() 関数を使用して一意の Symbol 値を作成します。

例

// Symbol を作成し、説明文字列を渡す(オプション)
var sym1 = Symbol("description");
var sym2 = Symbol("description");

// 作成される Symbol は毎回一意であり、説明が同じでも異なる
console.log("sym1 === sym2: " + (sym1 === sym2));
console.log("sym1: " + sym1.toString());

実行結果:

sym1 === sym2: false
sym1: Symbol(description)

一意性:これは Symbol の最も重要な特性であり、Symbol() を呼び出すたびに新しい値が作成され、他のどの値とも等しくなりません。


オブジェクトのプロパティとしての Symbol

Symbol はオブジェクトのプロパティキーとして使用でき、一意のプロパティ名を作成します。

例

// プロパティキーとして Symbol を作成
var sym = Symbol("key");

// Symbol をオブジェクトのプロパティキーとして使用
var obj = {
    name: "Alice",  // 通常の文字列プロパティ
    [sym]: "secret value"  // Symbol プロパティ、算出プロパティ名
};

// 通常のプロパティにアクセス
console.log("通常のプロパティ: " + obj.name);
// Symbol プロパティにアクセス
console.log("Symbol プロパティ: " + obj[sym]);
// Symbol プロパティは JSON に表示されない
console.log("オブジェクト: " + JSON.stringify(obj));

実行結果:

普通属性: Alice
Symbol 属性: secret value
对象: {"name":"Alice"}

プライバシー:Symbol プロパティは JSON シリアライズに含まれず、for...in でも列挙されないため、"プライベート"プロパティの作成に使用できます。


グローバル Symbol レジストリ

Symbol.for() を使用してグローバルレジストリ内の Symbol にアクセスすると、同じキーに対して同じ Symbol が返されます。

例

// Symbol.for メソッドを使用してグローバル Symbol を作成/取得
// キーが存在しない場合は新規作成し、存在する場合は既存のものを返す
var globalSym1 = Symbol.for("global");
var globalSym2 = Symbol.for("global");

// 同じキーの Symbol は等しい
console.log("グローバル Symbol が等しい: " + (globalSym1 === globalSym2));

// Symbol のキーを取得
console.log("Symbol key: " + Symbol.keyFor(globalSym1));

実行結果:

全局 Symbol 相等: true
Symbol key: global

違い:Symbol() は毎回新しい値を作成し、Symbol.for() はグローバルレジストリ内を検索して作成します。


組み込み Symbol

JavaScript には、言語の動作をカスタマイズするための組み込み Symbol 値がいくつか定義されています。

例

// Symbol.iterator はオブジェクトのデフォルトのイテレータを定義するために使用
var arr = [1, 2, 3];
// 配列のイテレータを取得
var iterator = arr[Symbol.iterator]();

// イテレータを使用して反復処理
console.log("最初の要素: " + iterator.next().value);
console.log("2番目の要素: " + iterator.next().value);

// Symbol.toStringTag でオブジェクトの toString() の戻り値をカスタマイズ
var obj = {
    [Symbol.toStringTag]: "MyObject"
};
console.log("オブジェクト型: " + obj.toString());

実行結果:

第一个元素: 1
第二个元素: 2
オブジェクトタイプ: [object MyObject]

重要:組み込み Symbol は、イテレータや型変換などの言語動作をカスタマイズするために使用され、JavaScript の高度な機能の基盤です。


Symbol型注釈

TypeScript では Symbol 型を使用して型注釈を行います。

例

// Symbol 型注釈
var sym: symbol = Symbol("key");

// オブジェクトのキーの型は symbol、値は string
var obj: { [key: symbol]: string } = {};

// キーとして Symbol を使用
obj[sym] = "value";
console.log("Symbol プロパティ値: " + obj[sym]);

型:TypeScript ではsymbolSymbol 値を型注釈します。


注意事項

  • 一意性:Symbol() の呼び出しごとに値が異なる
  • 列挙不可:Symbol プロパティは for...in ループに表示されない
  • JSON で無視:Symbol プロパティは JSON にシリアライズされない
  • グローバル登録:Symbol.for() はグローバルレジストリで共有される

適用シーン:Symbol は、オブジェクトのプライベートプロパティの作成、一意の定数の定義、プロパティ名の衝突回避などによく使用されます。


まとめ

Symbol は TypeScript において重要なプリミティブ型です。

  • 一意性:作成された Symbol は毎回等しくない
  • プロパティキー:オブジェクトの一意のプロパティキーとして使用可能
  • グローバル登録:Symbol.for() でグローバル Symbol を作成/取得
  • 組み込み Symbol:Symbol.iterator、Symbol.toStringTag など
  • 型注釈:symbol 型を使用

推奨:一意の識別子を作成する必要がある場合、プロパティ名の衝突を避ける場合、または"プライベート"プロパティが必要な場合は、Symbol を使用します。

その他の拡張