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 Boolean
や new String
、new 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) == sym
はtrue
を返します。 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
仕様
ブラウザー実装状況
BCD tables only load in the browser