はじめに
JavaScriptにおけるSymbolというプリミティブ値をご存知でしょうか。
この記事ではSymbolというものが何なのか、何のために存在するのか紹介したいと思います。
この記事は、MDNのSymbolの説明と、Symoblの存在意義を問うStackOverflowの内容に基づいて作成しています。
Symbolとは
MDNでは下記のように説明されています。
Symbol は組み込みオブジェクトであり、コンストラクターは一意であることが保証されているシンボルプリミティブ(シンボル値または単にシンボル)を返します。シンボルは、他のコードがオブジェクトに追加する可能性のあるキーと衝突しないように、また、他のコードがオブジェクトにアクセスするために通常使用するメカニズムから隠されるるように、一意のプロパティキーをオブジェクトに追加するためによく使用されます。これによって弱いカプセル化、または弱い形の情報隠蔽が実現できます。
私はMDNの記事を読み、Symbolを呼び出すととにかく一位な値が返ってくると理解しました。
例えばこんな感じ:
Symbol("foo") === Symbol("foo"); // false
なぜこんなものが存在するのか
Symbolがどういったモノなのかは理解できましたが、必要性に関しては疑問が残りました。興味が沸いたので更に検索していくと、2014年ごろに投稿されたStackOverflowのディスカッションを見つけたので下記にまとめました。
プライベートプロパティのための提案だった
Symbolの最初の提案は「private_name_object」という名前で、オブジェクトの内部プロパティを外部から隠すための仕組みとして構想されていました。
ただし、実際に実装されたSymbolは完全なプライベート性を持っているわけではありません。たとえば、Object.getOwnPropertySymbols() を使えば、Symbolキーを取得できます。
それでも、従来のプロパティ定義方法と比較すると、Symbolを使うことで名前の衝突を防ぎやすくなるという大きな利点があります。
ユニークなキーとしての利用
通常のオブジェクトのキーは文字列であるため、次のような衝突が起こり得ます:
const obj = {
"id": 1,
"id": 2
};
console.log(obj.id); // 2(上書き)
一方でSymbolを使えば、同じ文字列であっても別のキーとして扱われるため、衝突が起きません:
const id1 = Symbol("id");
const id2 = Symbol("id");
const obj = {
[id1]: 1,
[id2]: 2
};
console.log(obj[id1]); // 1
console.log(obj[id2]); // 2
まとめ
MDNの記事とStackOverflowのディスカッションを通じて、もともとの提案とは違うものが実装されたということと、ユニーク性の確保に便利だということがわかりました。
これからはソースコードなどで見つけたら、ユニークなんだなとおもいたいd