Symbol

データ型 symbol は、プリミティブデータ型です。Symbol() 関数は、symbol 型の値を返します。これは組み込みオブジェクトを公開するための静的プロパティを持ち、グローバルシンボルレジストリを公開するための静的メソッドを持つので、組み込みオブジェクトクラスのようにも見えますが、コンストラクターとしての機能を持たず、"new Symbol()" はサポートされていません。

Symbol() から返されるすべてのシンボル値は一意です。シンボル値は、オブジェクトプロパティの識別子として使用できます。これがデータ型の主な利用目的ですが、不透明なデータ型の有効化や、実装サポートされている一意の識別子として機能するなど、他の利用目的も存在します。目的や使用方法に関する詳細を知りたい場合、MDN用語集:Symbol を見てください。

説明

新しいプリミティブシンボルを生成するために、説明のためのオプション文字列とともに Symbol() を記述します。

let sym1 = Symbol()
let sym2 = Symbol('foo')
let sym3 = Symbol('foo')

上のコードでは、3 つの新しいシンボルを作成しています。Symbol('foo') は文字列 'foo' を強制的にシンボルにしているわけではなく、毎回新しいシンボルを生成していることに注意してください。

Symbol('foo') === Symbol('foo')  // false

次の new 演算子を用いた構文では、TypeError が投げられます。

let sym = new Symbol()  // TypeError

これにより、新しいシンボル値を生成する代わりに明示的な Symbol ラッパーオブジェクトを生成することを防ぎます。プリミティブデータ型の周りに明示的なラッパーオブジェクトを生成することは、もはや ECMAScript6 ではサポートされていません。しかし、new Booleannew Stringnew Number のような既存のプリミティブラッパーオブジェクトは、歴史的な理由からまだ生成できます。

もし本当に Symbol ラッパーオブジェクトを生成したいのなら、Object() 関数を使用できます。

let sym = Symbol('foo')
typeof sym      // "symbol"
let symObj = Object(sym)
typeof symObj   // "object"

グローバルシンボルレジストリの共有シンボル

上述の Symbol() 関数を使用した構文は、コードベース全体で使用できるグローバルシンボルは作成されません。ファイルを跨いでグローバルスコープのような環境でも利用可能なシンボルを作成するには、Symbol.for()Symbol.keyFor() のメソッドを使用して、グローバルシンボルレジストリからシンボルを設定および取得します。

オブジェクトのシンボルプロパティを探す

Object.getOwnPropertySymbols() メソッドは、シンボルの配列を返し、与えられたオブジェクトのシンボルプロパティを見つけることができます。すべてのオブジェクトは、シンボルなしで初期化されます。そのため、オブジェクトにシンボルプロパティを設定しないかぎり、この配列は空だということに注意してください。

コンストラクター

Symbol()
新しい Symbol オブジェクトを作成します。"new Symbol()" という構文をサポートしていないので、コンストラクターとしては不完全です。

静的プロパティ

Symbol.asyncIterator
オブジェクトのデフォルトの AsyncIterator を返すメソッド。for await...of によって使用されます。
Symbol.hasInstance
コンストラクターのオブジェクトがオブジェクトをインスタンスとして認識しているかどうかを判定するメソッド。instanceof によって使用されます。
Symbol.isConcatSpreadable
オブジェクトをその配列要素にフラット化する必要があるかどうかを示すブール値。Array.prototype.concat() によって使用されます。
Symbol.iterator
オブジェクトのデフォルトのイテレーターを返すメソッド。for...of によって使用されます。
Symbol.match
文字列と照合するメソッド。オブジェクトを正規表現として使用できるかどうかを判断するためにも使用されます。String.prototype.match() によって使用されます。
Symbol.matchAll
文字列に対する正規表現の一致を生成するイテレーターを返すメソッド。String.prototype.matchAll() によって使用されます。
Symbol.replace
文字列の一致した部分文字列を置き換えるメソッド。String.prototype.replace() によって使用されます。
Symbol.search
正規表現に一致する文字列内のインデックスを返すメソッド。String.prototype.search() によって使用されます。
Symbol.split
正規表現に一致するインデックスで文字列を分割するメソッド。String.prototype.split() によって使用されます。
Symbol.species
派生オブジェクトを作成するためのコンストラクタ関数。
Symbol.toPrimitive
オブジェクトをプリミティブ値に変換するメソッド。
Symbol.toStringTag
オブジェクトのデフォルトの説明に使用される文字列の値。Object.prototype.toString() によって使用されます。
Symbol.unscopables
自身のプロパティ名と継承されたプロパティ名が、関連付けられたオブジェクトの with 環境バインディングから除外されているオブジェクトの値。

静的メソッド

Symbol.for(key)
指定された key を使用して既存のシンボルを検索し、見つかればそれを返します。そうでない場合は、この key で グローバルシンボルレジストリに新しいシンボルが作成されます。
Symbol.keyFor(sym)
指定したシンボルのグローバルシンボルレジストリから共有シンボルキーを取得します。

インスタンスプロパティ

Symbol.prototype.description
シンボルの説明を含む読み取り専用の文字列。

インスタンスメソッド

Symbol.prototype.toSource()
Symbol オブジェクトのソースを含む文字列を返します。Object.prototype.toSource() メソッドを上書きします。
Symbol.prototype.toString()
シンボルの説明を含む文字列を返します。Object.prototype.toString() メソッドを上書きします。
Symbol.prototype.valueOf()
Symbol オブジェクトのプリミティブ値を返します。Object.prototype.valueOf() メソッドを上書きします。
Symbol.prototype[@@toPrimitive]
Symbol オブジェクトのプリミティブ値を返します。

シンボルと一緒に typeof 演算子を使用する

typeof 演算子は、シンボルを識別するために役立ちます。

typeof Symbol() === 'symbol'
typeof Symbol('foo') === 'symbol'
typeof Symbol.iterator === 'symbol'

シンボルの型変換

シンボルの型変換作業を行うとき、いくつかの点に注意してください。

  • シンボルを数値に変換しようとすると、TypeError が投げられます(例: +sym または sym | 0 )。
  • 緩い等価演算子を使うとき、Object(sym) == symtrue を返します。
  • Symbol('foo') + 'bar'TypeError(シンボルを文字列に変換できません)を投げます。これは新しい文字列プロパティ名を暗黙的に生成することを防ぎます。
  • "安全な" String(sym) 変換はシンボルとともに Symbol.prototype.toString() を呼び出したかのように動作しますが、new String(sym) は TypeError を投げることに注意してください。

シンボルと for...in による反復

シンボルは for...in よる反復からは取得できません。加えて、Object.getOwnPropertyNames() はシンボルオブジェクトプロパティを返しません、それらを取得するために Object.getOwnPropertySymbols() を使うことができます。

let obj = {}

obj[Symbol('a')] = 'a'
obj[Symbol.for('b')] = 'b'
obj['c'] = 'c'
obj.d = 'd'

for (let i in obj) {
   console.log(i)  // logs "c" and "d"
}

シンボルと JSON.stringify()

JSON.stringify() を使用するとき、シンボルをキーとしたプロパティは完全に無視されます。

JSON.stringify({[Symbol('foo')]: 'foo'})
// '{}'

詳しくは JSON.stringify() を見てください。

プロパティキーとしてのシンボルラッパーオブジェクト

シンボルラッパーオブジェクトがプロパティキーとして使用されている場合、このオブジェクトはそのラップされたシンボルを強制的に使用します。

let sym = Symbol('foo')
let obj = {[sym]: 1}
obj[sym]             // 1
obj[Object(sym)]     // still 1

仕様

仕様書
ECMAScript (ECMA-262)
Symbol の定義

ブラウザー実装状況

BCD tables only load in the browser

関連項目