JavaScript | 基礎構文:データ型 – Symbol

JavaScript
スポンサーリンク

JavaScript入門:Symbol(ユニークな識別子)とは

Symbolは「絶対に重ならない一意の値」を作るためのデータ型です。オブジェクトの“衝突しないキー”や、内部的な印(タグ)として使われます。文字列や数値のように見えますが、性質がまったく違います。


基本:常にユニークな値を作る

  • 同じ説明(ラベル)を付けても、作られる値は毎回別物です。
const s1 = Symbol("id");
const s2 = Symbol("id");
console.log(s1 === s2); // false(説明が同じでも別物)
JavaScript
  • 型は symbol
console.log(typeof s1); // "symbol"
JavaScript
  • 文字列連結はできません(TypeError)。表示したいときは String(sym)sym.description を使います。
const tag = Symbol("tag");
// console.log("Tag: " + tag); // TypeError
console.log("Tag: " + String(tag));     // "Tag: Symbol(tag)"
console.log(tag.description);           // "tag"
JavaScript

代表的な使いどころ

1. オブジェクトの“衝突しないキー”として使う

  • ライブラリ同士や別ファイルでも、同名キーの上書きを避けられます。
const ID = Symbol("id");
const user = { name: "Taro", [ID]: 12345 };

console.log(user[ID]);     // 12345
console.log(Object.keys(user)); // ["name"](Symbolキーは列挙に出ない)
JavaScript

2. 半プライベートなデータを隠す

  • Object.keysfor...in に現れず、JSONにも含まれないため“見えにくい”保存場所になります。
const secret = Symbol("secret");
const obj = { public: 1, [secret]: "hidden" };

console.log(JSON.stringify(obj)); // {"public":1}(Symbolは無視される)
JavaScript
  • ただし、完全な秘密ではありません。Object.getOwnPropertySymbols(obj) で取得できます。

3. 既定の動作を拡張する「有名なシンボル」を使う

  • 言語に組み込まれた特別なSymbolで、オブジェクトのふるまいを定義できます。
// 反復可能(for...of)にする
const collection = {
  items: [1, 2, 3],
  [Symbol.iterator]() {
    let i = 0;
    return {
      next: () => ({ value: this.items[i++], done: i > this.items.length })
    };
  }
};
for (const v of collection) console.log(v); // 1 2 3

// toString時のタグ名を変える
const person = { name: "Taro", [Symbol.toStringTag]: "Person" };
console.log(Object.prototype.toString.call(person)); // "[object Person]"
JavaScript

グローバルレジストリ:Symbol.for と Symbol.keyFor

  • 「同じ名前なら同じSymbol」を共有したいときは、レジストリを使います。
const a = Symbol.for("app.config");
const b = Symbol.for("app.config");
console.log(a === b); // true(レジストリ経由は共有される)
console.log(Symbol.keyFor(a)); // "app.config"
JavaScript
  • Symbol() は毎回ユニーク。Symbol.for() は名前に紐づく“共有Symbol”。

列挙と取得の挙動(知っておくと安心)

  • Object.keys(obj)for...inJSON.stringify(obj) は Symbolキーを無視します。
  • 取得したい場合は以下を使います。
const syms = Object.getOwnPropertySymbols(obj); // Symbolキー一覧
const all = Reflect.ownKeys(obj);               // 文字列+Symbolキーすべて
JavaScript

よくあるつまずきと回避策

  • 文字列連結できない → String(sym)sym.description を使う。
  • 完全な「秘密」ではない → Object.getOwnPropertySymbols で見つけられる。
  • NumberやStringとは混ぜて比較・連結しない → 振る舞いが違うため、キー用途やメタ情報に限定する。

実用ミニパターン

  • 名前衝突を避けたい拡張ポイント
const EXT = Symbol("ext");
const plugin = { [EXT]: () => "plugin-data" };
JavaScript
  • 「内部状態」を他コードから触られにくくする
const stateSym = Symbol("state");
class Counter {
  constructor() { this[stateSym] = 0; }
  inc() { this[stateSym]++; }
  value() { return this[stateSym]; }
}
const c = new Counter();
c.inc();
console.log(c.value()); // 1
JavaScript

ミニ練習

  • 問1:同じ説明で作った Symbol が等しいか確認せよ。
const s1 = Symbol("id");
const s2 = Symbol("id");
console.log(s1 === s2); // false
JavaScript
  • 問2:Symbolキーのプロパティを Object.keys で見えるか確認せよ。
const K = Symbol("k");
const obj = { a: 1, [K]: 2 };
console.log(Object.keys(obj));             // ["a"]
console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(k)]
JavaScript
  • 問3:レジストリを使って同じキーを共有せよ。
const x = Symbol.for("share");
const y = Symbol.for("share");
console.log(x === y);       // true
console.log(Symbol.keyFor(x)); // "share"
JavaScript

まとめ

  • Symbolは「絶対に被らない一意の値」。オブジェクトキーや内部タグに最適。
  • Symbol() は毎回ユニーク、Symbol.for() は名前で共有。
  • 列挙・JSONに出ないため“半プライベート”に使えるが、完全な秘匿ではない。
  • 有名シンボル(Symbol.iterator など)でオブジェクトの既定動作を拡張できる。
タイトルとURLをコピーしました