Symbol(シンボル)の基本(JavaScript)

  • #JavaScript

Symbol(シンボル)の基本 (JavaScript)

みなさん!こんにちは!

ネクストライブのかたやんです。

JavaScriptに関する情報をネットで検索した際、コードにSymbolというものが使用されているのをみたことがありませんか?

Symbol(シンボル)は、あまり知られていない機能だと思うので、困惑する人も多いのではないでしょうか。

そこで、今回は、JavaScriptのSymbol(シンボル)の基本について書いていきます。

それでは、さっそく見ていきましょう!

シンボルとは

シンボルとは、ECMAScript6で新しく追加されたData Typeです。

シンボルは、オブジェクトのプロパティの唯一性を保つことを目的にしています(キーが被ることを防ぐ)。

そのため、全く同じsymbol型のデータを作ることはできません(作成するたびに全く新しいシンボルができあがる)。

//こんなイメージ 
//Symbol()はシンボル作成メソッド
let a = Symbol('test');
let b = Symbol('test');

console.log(a == b); //false
console.log(Symbol('シンボル') == Symbol('シンボル')); //false

それでは、シンボルの使い方を見ていきましょう!

//Symbol()メソッドでシンボルの作成ができる
let symbolVar = Symbol(); 

//Symbol()メソッドに文字列の引数を与えることで、初期値を設定できる
let symbolVarSecond = Symbol('test'); 



console.log(symbolVar); //Symbol()
console.log(typeof symbolVar); //symbol

console.log(symbolVarSecond); //Symbol(test)
console.log(typeof symbolVarSecond); //symbol シンボルの中身がstring型でも、symbol型となる

シンボルの比較を行った場合、同じ値を持っていても、完全一致とはみなされません。

symbol
let symbolVar = Symbol();
let symbolVarSecond = Symbol();

console.log(symbolVar === symbolVarSecond); //false
console.log(symbolVar == symbolVarSecond); //false
let symbolVar = Symbol('test'); 
let symbolVarSecond = Symbol('test');

console.log(symbolVar === symbolVarSecond); //false
console.log(symbolVar == symbolVarSecond); //false

ちなみにですが、シンボルに対して、newキーワードを使用することはできません。

let symbolVar = new Symbol(); //Uncaught TypeError: Symbol is not a constructor at new Symbol (<anonymous>)

Symbol.for()

Symbol.for()は、レジストリから既存のシンボルを探しだし、それを再使用するメソッドです。

もし見つからなければ、新しくシンボルを作成し、レジストリに追加します。

もっと厳密にいうと、

Symbol.for()は、グローバルレジストリからグローバルシンボルを探し出し、再使用するメソッドです。

もし見つからなければ新しくグローバルシンボルを作成し、グローバルレジストリに追加します。

グローバルシンボルは、これまで説明してきたシンボル(レギュラーシンボル)とは、すこし毛色が違います。

レギュラーシンボルSymbol()メソッドで作成したもの

グローバルシンボルSymbol.for()メソッドで作成したもの、とここでは単純化します。

symbol

グローバルレジストリに関しては、ここではあまり踏み込みませんが、グローバルスコープよりも広いものというくらいの認識でokです。

それでは、実際にSymbol.for()メソッドをみていきましょう!

let symbolVar  = Symbol.for('test'); //新しくグローバルSymbol('test')を作成

let symbolVarSecond = Symbol.for('test'); //既存のグローバルSymbol('test')を探し出して再使用

console.log(symbolVar === symbolVarSecond ); //true  再使用しているため、trueを返す。
let symbolVar  = Symbol('test'); //新しくレギュラーSymbol('test')を作成

let symbolVarSecond = Symbol.for('test'); //既存のグローバルSymbol('test')を探し出したが、見つからなかったため、新しくグローバルSymbol('test')を作成

console.log(symbolVar === symbolVarSecond ); //false

グローバルレジストリは文字列キーを必要とするため、Symbol.for()に引数として与えられた値は文字列に変換されます。

symbol

このグローバルレジストリに対して、検索をかけるメソッドが存在します。

それが、次に紹介するSymbol.keyFor()です。

Symbol.keyFor()

Symbol.keyFor()メソッドを利用することで、引数のシンボルがグローバルレジストリに存在するか検索をすることができます。

もし検索がヒットすれば、文字列キーを返します。

なにもヒットしなければ、undefinedを返します。

let regularSymbol = Symbol('regular');
let globalSymbol = Symbol.for('global'); //グローバルレジストリに追加

console.log(Symbol.keyFor(regularSymbol)); //undefined
console.log(Symbol.keyFor(globalSymbol)); //global グローバルレジストリにて発見

ユースケース

Symbolは、他のData Type同様にプロパティとして使用することができます。

let symbol1 = Symbol('usecase');

let symbolProperty = { symbol1: 'this is usecase' };

let symbolProperty2 = { [symbol1]: 'this is usecase' };

//                         ↓[]がないとエラーが起きる
let symbolProperty3 = { [Symbol('test')]: 'this is test' };

console.log(symbolProperty); //{symbol1: "this is usecase"}
console.log(symbolProperty2); //{Symbol(usecase): "this is usecase"}
console.log(symbolProperty3); //{Symbol(test): "this is test"}

さいごに

以上が、Symbol(シンボル)の基本事項でした。

しかし、Symbolには、まだいくつかの機能が存在しています。

ザっと上げると

  • Symbol.asyncIterator
  • Symbol.hasInstance
  • Symbol.isConcatSpreadable
  • Symbol.iterator
  • Symbol.match
  • Symbol.replace
  • Symbol.search
  • Symbol.species
  • Symbol.split
  • Symbol.toPrimitive
  • Symbol.toStringTag
  • Symbol.unscopables

これくらいあります。

今回は、Symbol(シンボル)の基本事項の紹介にとどめておきます。

これらは今後、まとめて紹介しようと思います。

この記事が、少しでも、あなたの役に立つことができれば幸いです。

この記事を書いた人

おすすめRECOMMENDED