TypeScript Symbol
Symbol は ES6 で導入されたプリミティブデータ型で、一意の識別子を表します。
TypeScript では、Symbol をオブジェクトのプロパティキーとして使用でき、プロパティの一意性を保証します。
これは、プライベートプロパティを作成したり、プロパティ名の衝突を避けたりする場面で非常に役立ちます。
SVG 図解:Symbol の動作原理
なぜ Symbol が必要なのか
JavaScript では、オブジェクトのプロパティ名はすべて文字列であり、衝突が発生することがあります。
Symbol は一意の識別子を作成する方法を提供し、Symbol() を呼び出すたびに新しい一意の値が作成されます。
これは、プライベートプロパティの作成、一意の定数の定義、イテレータの実装などの場面で非常に役立ちます。
概念の説明:Symbol は JavaScript のプリミティブデータ型の一つで、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 はオブジェクトのプロパティキーとして使用でき、一意のプロパティ名を作成します。
例
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 が返されます。
例
// キーが存在しない場合は新規作成し、存在する場合は既存のものを返す
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 値がいくつか定義されています。
例
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 型を使用して型注釈を行います。
例
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 を使用します。