シンボル プリミティブは、他のシンボル プリミティブの値など、他の値と競合しない一意の値を表します。同じ文字で構成された 2 つの文字列プリミティブは、厳密に等しいと評価されます。
String() === String()
> true
String( "My string." ) === String( "My string." );
> true
ただし、Symbol()
関数を使用して作成された 2 つのシンボルが厳密に等しいということは決してありません。
Symbol() === Symbol()
> false
このトレイトを使用すると、オブジェクト内の一意のプロパティキーとしてシンボルを使用できるため、他のコードがそのオブジェクトに追加する可能性のあるキーとの競合を防ぐことができます。
const mySymbol = Symbol( "Desc" );
const myObject = {};
myObject[mySymbol] = "propSymbol";
myObject
> Object { Symbol("Desc"): "propSymbol" }
記号には次の 3 種類があります。
Symbol()
で作成された記号Symbol.for()
を使用してグローバル シンボル レジストリから設定および取得される共有シンボル- Symbol オブジェクトの静的プロパティとして定義された「よく知られたシンボル」。これらのシンボルには、誤って上書きされない内部メソッドが含まれています。
Symbol()
は、説明(または「シンボル名」)をオプションの引数として受け入れます。これらの説明は、デバッグ目的の人間可読ラベルであり、結果の一意性には影響しません。Symbol
の呼び出しは、複数の呼び出しで説明が同じであっても、完全に一意のシンボル プリミティブを返します。
Symbol( "My symbol." ) === Symbol( "My symbol." );
> false
他のプリミティブ データ型と同様に、シンボルはプロトタイプからメソッドとプロパティを継承します。たとえば、作成したシンボルの継承プロパティとして説明にアクセスできます。
let mySymbol = Symbol( "My symbol." );
mySymbol.description
> "My symbol."
ただし、new
キーワードを使用してシンボルを作成することはできません。
let mySymbol = new Symbol();
> Uncaught TypeError: Symbol is not a constructor
シンボルは列挙できません。つまり、標準メソッドを使用してシンボルを反復処理する場合、シンボル プロパティは使用できません。getOwnPropertySymbols()
メソッドを使用すると、オブジェクトのシンボル プロパティにアクセスできます。
共有記号
Symbol.for()
メソッドは、指定された文字列をキーとして、ランタイム全体のグローバル シンボル レジストリ内の既存のシンボルを検索し、一致するシンボルが見つかった場合はそのシンボルを返します。見つからない場合は、指定されたキーを持つシンボルが作成され、グローバル レジストリに追加されます。
let sharedSymbol = Symbol.for( "My key." );
sharedSymbol === Symbol.for( "My key." )
> true
これらのキーは、作成者が作成した Symbol
プリミティブに割り当てられた説明と機能的に重複しません。シンボル レジストリ内のシンボルにアクセスするには、まず for()
を使用してシンボルを作成する必要があります。
Symbol( "String" ) === Symbol( "String" );
> false
Symbol( "String" ) === Symbol.for( "String" );
> false
Symbol.for( "String" ) === Symbol.for( "String" );
> true
シンボル レジストリからシンボルのキーを取得するには、Symbol.keyFor()
を使用します。
let mySymbol = Symbol.for( "Key." );
Symbol.keyFor( mySymbol ) ;
> "Key."
「よく知られている」記号
既知のシンボルは Symbol
オブジェクトの静的プロパティであり、それぞれがシンボル自体です。既知のシンボルを使用すると、JavaScript の組み込みメソッドにアクセスして変更するための一意のプロパティキーを指定できます。また、コア動作が意図せず上書きされるのを防ぐこともできます。
Symbol;
> function Symbol()
asyncIterator: Symbol(Symbol.asyncIterator)
for: function for()
hasInstance: Symbol("Symbol.hasInstance")
isConcatSpreadable: Symbol("Symbol.isConcatSpreadable")
iterator: Symbol(Symbol.iterator)
keyFor: function keyFor()
length: 0
match: Symbol("Symbol.match")
matchAll: Symbol("Symbol.matchAll")
name: "Symbol"
prototype: Object { … }
replace: Symbol("Symbol.replace")
search: Symbol("Symbol.search")
species: Symbol("Symbol.species")
split: Symbol("Symbol.split")
toPrimitive: Symbol("Symbol.toPrimitive")
toStringTag: Symbol("Symbol.toStringTag")
unscopables: Symbol("Symbol.unscopables")
<prototype>: function ()
シンボルは ES6 固有の機能であるため、これらのシンボリック値は、下位互換性の問題を引き起こすことなく JavaScript の動作を変更するデベロッパーの「拡張ポイント」として使用することを目的としています。
よく知られたシンボル値は、キーと変更可能なプロトタイプを区別するために、@@
接頭辞でスタイル設定されるか、%
でラップされることがよくあります。たとえば、@@match
(または %match%
)は、String.prototype.match
ではなく、不変の Symbol.match
への参照です。
理解度を確認する
new
を使用して記号を作成できますか?
次のどれが「よく知られている」記号を説明していますか。