JavaScript/Symbol
Symbolは、ECMAScript 2015(ECMASCript 6th Edition: ES6)で導入された新しいデータ型であり、プリミティブ型の一種です[1]。 Symbolは、ユニークな識別子を生成するために使用されます。 従来のJavaScriptの文字列や数値とは異なり、Symbolは他のどの値とも異なることが保証されています。 Symbolは、オブジェクトのプロパティ名として使用されることが多く、ES6で導入された新しい機能であるプロキシや反復子などでも使用されています。 このチュートリアルでは、Symbolの基本的な使い方、作成方法、プロパティ、メソッド、および実用的な例について解説します。
Symbolの基本的な使い方
[編集]Symbolは、プリミティブデータ型の一つであり、一意の識別子を作成するために使用されます。Symbolは、文字列とは異なり、値が一意であるため、異なる場所で同じSymbolを使用することができます。Symbolは、通常オブジェクトのプロパティ名として使用され、他のプロパティ名と混同されることがないようにするために使用されます。
作成方法
[編集]Symbolを作成するには、グローバルなSymbol()関数を呼び出します。引数を渡すことができますが、引数は説明的な目的でのみ使用され、Symbolの一意性には影響を与えません。
const sym1 = Symbol(); const sym2 = Symbol('description');
プロパティ
[編集]Symbolには、次のようなプロパティがあります。
Symbol.asyncDispose
[編集]非同期リソースのクリーンアップ処理を定義するために使用されます。特定のオブジェクトが非同期処理終了時にリソースを解放する際に役立ちます。
Symbol.asyncIterator
[編集]非同期イテレーターを定義するために使用されます。このシンボルを持つメソッドを実装することで、オブジェクトを for await...of
ループで反復処理できるようになります。
Symbol.dispose
[編集]リソースの同期的なクリーンアップ処理を定義するために使用されます。このシンボルを利用して、特定のオブジェクトのスコープを抜けたときにリソースを解放できます。
Symbol.hasInstance
[編集]instanceof
演算子のカスタマイズを可能にします。このシンボルを持つメソッドを実装することで、オブジェクトが特定のクラスやコンストラクタと互換性があるかどうかを定義できます。
Symbol.isConcatSpreadable
[編集]Array.prototype.concat()
メソッドを使用した際に、オブジェクトを展開するかどうかを制御するために使用されます。true
に設定すると、配列のように展開されます。
Symbol.iterator
[編集]オブジェクトのデフォルトのイテレーター関数を定義するために使用されます。このシンボルを持つメソッドを実装することで、オブジェクトを for...of
ループで反復処理できるようになります。
Symbol.length
[編集]このシンボルはまだ正式に仕様に含まれていませんが、将来的に特定のオブジェクトの長さ情報を扱うために使用される可能性があります。
Symbol.match
[編集]String.prototype.match()
メソッドが呼び出された際に、オブジェクトのカスタム動作を定義するために使用されます。
Symbol.matchAll
[編集]String.prototype.matchAll()
メソッドが呼び出された際に、オブジェクトのカスタム動作を定義するために使用されます。すべての一致を反復可能なオブジェクトとして返します。
Symbol.name
[編集]Symbolオブジェクトの名前。 'Symbol'
Symbol.prototype
[編集]すべてのシンボルが継承するプロトタイプオブジェクトを表します。シンボルに関連するメソッドが定義されています。
Symbol.replace
[編集]String.prototype.replace()
メソッドが呼び出された際に、オブジェクトのカスタム動作を定義するために使用されます。
Symbol.search
[編集]String.prototype.search()
メソッドが呼び出された際に、オブジェクトのカスタム動作を定義するために使用されます。
Symbol.species
[編集]派生オブジェクトを作成する際に、その元となるオブジェクトのコンストラクタを参照するために使用されます。例えば、配列メソッドが新しい配列を返す際に使用されます。
Symbol.split
[編集]String.prototype.split()
メソッドが呼び出された際に、オブジェクトのカスタム動作を定義するために使用されます。
Symbol.toPrimitive
[編集]オブジェクトをプリミティブ値に変換する際のカスタム動作を定義するために使用されます。このシンボルを持つメソッドを実装することで、数値や文字列などの変換方法を制御できます。
Symbol.toStringTag
[編集]オブジェクトの文字列表現に使用されるシンボルです。このシンボルをカスタマイズすることで、Object.prototype.toString.call(obj)
の出力を制御できます。
Symbol.unscopables
[編集]with
文のスコープ内で無視されるプロパティを定義するために使用されます。このシンボルを設定することで、with
文の挙動をカスタマイズできます。
メソッド
[編集]Symbolには、次のようなメソッドがあります。
Symbol.for()
[編集]グローバルシンボルレジストリから、指定されたキーに対応するSymbolを返します。存在しない場合は新しいSymbolを作成します。
Symbol.keyFor()
[編集]- Symbol.for(key): グローバルシンボルレジストリから、指定されたSymbolに対応するキーを返します。存在しない場合はundefinedを返します。
実用的な例
[編集]Symbolは、オブジェクトのプロパティ名として使用されることが多く、以下のような例があります。
const MY_KEY = Symbol(); const obj = {}; obj[MY_KEY] = 123; console.log(obj[MY_KEY]); // 123
また、グローバルシンボルレジストリを使用して、アプリケーション全体で一意のシンボルを共有することができます。例えば、以下のようにして、シンボルを共有することができます。
- module1.js
const MY_KEY = Symbol.for('my key');
- module2.js
const MY_KEY = Symbol.for('my key'); console.log(MY_KEY === module1.MY_KEY); // true
Well-known symbols
[編集]Well-known symbolsは、JavaScriptにおいて標準的に定義されたシンボルで、特定の動作をするために使用されます。
以下は、Well-known symbolsの一覧表です。
Well-known symbol | 説明 |
---|---|
Symbol.iterator | オブジェクトに対するデフォルトの反復子を定義します。 |
Symbol.asyncIterator | オブジェクトに対する非同期反復子を定義します。 |
Symbol.match | 正規表現にマッチする文字列を返すメソッドを定義します。 |
Symbol.replace | 正規表現にマッチする部分を置換するメソッドを定義します。 |
Symbol.search | 正規表現にマッチする最初のインデックスを返すメソッドを定義します。 |
Symbol.split | 正規表現にマッチする部分で文字列を分割するメソッドを定義します。 |
Symbol.hasInstance | オブジェクトがあるクラスのインスタンスであるかどうかを判定するメソッドを定義します。 |
Symbol.isConcatSpreadable | オブジェクトがArray.prototype.concat()の展開時に配列に変換されるかどうかを定義します。 |
Symbol.unscopables | with文でスコープ外にするプロパティの一覧を定義します。 |
Symbol.toPrimitive | オブジェクトをプリミティブ型に変換するメソッドを定義します。 |
Symbol.toStringTag | オブジェクトの型を示す文字列を定義します。 |
Symbol.species | オブジェクトのコンストラクタ関数を返すメソッドを定義します。 |
Symbol.for(key) | 名前付きシンボルを取得します。 |
Symbol.keyFor(sym) | 名前付きシンボルのキーを取得します。 |
これらのシンボルは、JavaScriptの標準的な動作をカスタマイズしたり、自分で定義したオブジェクトに特定の機能を追加するために使用されます。
附録
[編集]チートシート
[編集]以下は、JavaScriptのSymbolに関するチートシートです。
// Symbolの基本的な使い方 const mySymbol = Symbol('mySymbol'); // 作成方法 const symbol1 = Symbol(); const symbol2 = Symbol('symbol2'); // プロパティ console.log(Symbol.iterator); // Symbol(Symbol.iterator) // メソッド const symbol3 = Symbol.for('symbol3'); console.log(Symbol.keyFor(symbol3)); // symbol3 // 実用的な例 const myObj = {}; const mySymbol1 = Symbol('mySymbol1'); const mySymbol2 = Symbol('mySymbol2'); myObj[mySymbol1] = 'value1'; myObj[mySymbol2] = 'value2'; console.log(myObj[mySymbol1]); // value1 console.log(myObj[mySymbol2]); // value2
上記のコードでは、以下の内容を含んでいます。
- 基本的なSymbolの使い方
- Symbolの作成方法に関する例
- Symbolオブジェクトのプロパティの例(Symbol.iterator)
- Symbolオブジェクトのメソッドの例(Symbol.for、Symbol.keyFor)
- 実用的な例として、Symbolを使ってオブジェクトにプロパティを追加する例
このチートシートは、Symbolの基本的な使い方やプロパティ、メソッド、実用的な例を網羅しています。 これらの情報を参考に、Symbolを使った開発をスムーズに進めていくことができるでしょう。
用語集
[編集]- Symbol: ES2015で導入されたプリミティブ型の一つで、一意の識別子を作成するために使用されます。
- Symbol.for(key): グローバルなシンボルレジストリを介して、指定されたキーで登録された既存のシンボルを返します。存在しない場合は、新しいシンボルを作成します。
- Symbol.keyFor(sym): グローバルなシンボルレジストリから、指定されたシンボルに関連付けられたキーを取得します。キーが見つからない場合はundefinedを返します。
- Symbol.iterator: オブジェクトがfor...ofループで反復可能であることを示すシンボルです。
- Well-known symbols: 既存のシンボルのうち、特定の目的で予約されているものを示す用語です。例えば、Symbol.iteratorはWell-known symbolsの一つです。
- Symbol.species: インスタンスを作成するためのファクトリーメソッドを持つコンストラクタ関数において、生成されるオブジェクトの種類を表すシンボルです。
- Symbol.hasInstance: オブジェクトが特定のコンストラクタ関数のインスタンスであるかどうかを判定するために使用されるシンボルです。
- Symbol.toStringTag: オブジェクトのデフォルトの文字列化時に使用されるタグ名を表すシンボルです。
- Symbol.match: 正規表現のマッチングを行うためのシンボルです。
- Symbol.toPrimitive: オブジェクトをプリミティブ値に変換するためのシンボルです。
- Symbol.isConcatSpreadable: 配列をconcat()メソッドで展開するかどうかを示すシンボルです。
- Symbol.unscopables: with文によってスコープされないプロパティ名の集合を表すシンボルです。
- Symbol.asyncIterator: オブジェクトがfor-await-ofループで反復可能であることを示すシンボルです。