sosukesuzuki.dev

2022年 sosukesuzuki 1人アドベントカレンダー

December, 17 2022

JavaScript の Symbol の分類

2022年の sosukesuzuki 1人アドベントカレンダー 17 日目です。

JavaScript には Symbol というプリミティブなデータ型があります。まあまあ便利で色々使ったりすると思います。

さて、Symbol は 3 種類に分類できます。

1 つめは Symbol コンストラクタ で普通に作ったユニークなシンボルです。

const s = Symbol("foo");

こういうやつですね。よく見る。

2 つめは Symbol.for で作った、いわゆる Registered Symbol というシンボルです。

Symbol.for は引数で与えられたキーに対応するシンボルを、ランタイムごとに存在するグローバルシンボルレジストリから探して返します。対応するシンボルが見つからなければ新たに作成してグローバルシンボルレジストリに登録した上で返します。つまり、同じキーで Symbol.for を複数回呼び出すと、毎回同じシンボルへとアクセスできます。

const s1 = Symbol.for("foo");
const s2 = Symbol.for("foo");

console.log(s1 === s2); // true

逆に Symbol コンストラクタは毎回異なるシンボルを作成して返します。

const s1 = Symbol("foo");
const s2 = Symbol("foo");

console.log(s1 === s2); // false

3 つめは Well-known Symbols です。Symbol.iterator のようにあらかじめ設定されているシンボルで、ECMAScript の様々な挙動において特別な扱いを受けます。

console.log(typeof Symbol.iterator); // "symbol"
console.log(typeof Symbol.hasInstance); // "symbol"

表にまとめます。

種類
ユニークなシンボル Symbol("foo")
Registered symbol Symbol.for("foo")
Well-known symbol Symbol.iterator

現在 Stage 3 の Symbols as WeakMap keys というプロポーザルがあります。これは名前の通り Symbol を WeakMap のキーとして使えるようにするプロポーザルです。

シンボルは、その種類によって GC で回収されるかどうかにも違いがあるので、その特性によって WeakMap のキーとするべきかどうか、というのも変わってきます。Symbols as WeakMap keys のプロポーザルの仕様として、まだ最終的にどのシンボルを WeakMap のキーとして許容するのか結論は出ていないようです。

が、どちらにしてもシンボルの種類をなんらかの方法で判断できると便利そうです。そこで、新しいプロポーザル Symbol Predicates が誕生しました。Symbol Predicates は次の 2 つの関数を提供します。

  • Symbol.isRegistered(symbol)
  • Symbol.isWellKnown(symbol)

名前の通り、それぞれあるシンボルが Registerd symbol であるかどうか、Well-known symbol であるかどうかを判定します。どちらにも当てはまらなければ通常のユニークなシンボルというわけです。

まあ便利そうですね。

参考リンク