JavaScriptのシンボルを使って一意なオブジェクトプロパティを定義

JavaScriptのシンボルを使って一意なオブジェクトプロパティを定義

シンボルは、JavaScriptにおけるユニークな識別子を作成するためのプリミティブ型です。本記事では、シンボルを使った一意なオブジェクトプロパティの定義とその活用方法について掘り下げます。

シンボルの基本

シンボルは、Symbol()を使用して作成され、一意な値を持ちます。

const sym1 = Symbol();
const sym2 = Symbol();
console.log(sym1 === sym2); // false

シンボルをオブジェクトプロパティに使用

シンボルはプロパティの衝突を防ぎます。

const uniqueKey = Symbol();
const obj = {
  [uniqueKey]: 'This is unique'
};
console.log(obj[uniqueKey]); // This is unique

シンボルプロパティのアクセス

シンボルプロパティは通常のfor...inでは列挙されません。

const symKey = Symbol('key');
const obj = { [symKey]: 'value', normalKey: 'normalValue' };

for (let key in obj) {
  console.log(key); // normalKey
}

console.log(Object.getOwnPropertySymbols(obj)); // [ Symbol(key) ]

シンボルの説明

シンボルには説明(description)を付けることができます。

const sym = Symbol('description');
console.log(sym.description); // description

グローバルシンボル

Symbol.for()でグローバルレジストリにシンボルを登録します。

const globalSym = Symbol.for('globalKey');
const anotherGlobalSym = Symbol.for('globalKey');
console.log(globalSym === anotherGlobalSym); // true

グローバルシンボルの検索

Symbol.keyFor()を使うと、登録済みシンボルのキーを取得できます。

const sym = Symbol.for('sharedKey');
console.log(Symbol.keyFor(sym)); // sharedKey

シンボルを使ったクラスのカプセル化

プライベートプロパティとしてシンボルを使用できます。

const privateKey = Symbol();
class MyClass {
  constructor(value) {
    this[privateKey] = value;
  }
  getPrivateValue() {
    return this[privateKey];
  }
}

const instance = new MyClass('secret');
console.log(instance.getPrivateValue()); // secret
console.log(instance.privateKey); // undefined

シンボルを使ったメタデータの付加

シンボルを利用してメタデータを追加します。

const metadataKey = Symbol('metadata');
const obj = {
  [metadataKey]: { author: 'Alice', version: 1 }
};

console.log(obj[metadataKey]); // { author: 'Alice', version: 1 }

組み込みのシンボル

JavaScriptには特別な目的を持つ組み込みシンボルが用意されています。

class MyArray extends Array {
  static get [Symbol.species]() {
    return Array;
  }
}

const arr = new MyArray(1, 2, 3);
const filtered = arr.filter(x => x > 1);
console.log(filtered instanceof MyArray); // false
console.log(filtered instanceof Array); // true

シンボルを用いたマジックメソッド

Symbol.iteratorを使用して反復可能なオブジェクトを作成します。

const iterable = {
  [Symbol.iterator]() {
    let count = 0;
    return {
      next() {
        count++;
        return count <= 3
          ? { value: count, done: false }
          : { done: true };
      }
    };
  }
};

for (const value of iterable) {
  console.log(value); // 1, 2, 3
}

注意点とベストプラクティス

シンボルは独特の機能を持っていますが、使用頻度を見極める必要があります。例えば、プロパティの衝突を避けたい場合や特定の操作をカプセル化したい場合に効果的です。

まとめ

JavaScriptのシンボルを使うことで、プロパティの衝突を防ぎ、カプセル化やメタデータの管理が簡単になります。組み込みシンボルやグローバルシンボルを活用して、効率的で堅牢なコードを書きましょう。