Symbol(シンボル)

(標準組み込みオブジェクト)
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Symbol

Symbol([description])

シンボルはES2015から新たに導入されたプリミティブデータ型(オブジェクトではないデータ型)の1つである。
引数の description にはデバッグの際にシンボルを見分けるための文字列を指定する。
シンボルはSymbol関数によってのみ作成することができる。シンボルの実体は「唯一無二の何か」であり、決して競合しないユニークなキーのようなものだが、文字列データではない。そのため、console.logで中身を見ようとしても文字表現ができないため、値が出力されない。

const sym = Symbol();
console.log(sym); // [object Symbol] { ... }
console.log(typeof sym); // symbol

一旦作ったシンボルは、それ自身とのみ等しくなる。同じものを作ることはできない。そういう意味では空のオブジェクトに近いかもしれないだろう。

const sym1 = Symbol();
const sym2 = Symbol();
console.log(sym1 === sym2); // false

シンボルを生成する際にはnew演算子は不要である(newを使うとエラーになる)。また、Symbol()関数はパラメータを1つ指定することができるが、このパラメータはデバッグ用途なので生成されるシンボル自体には影響を与えない。

const sym1 = Symbol();
const sym2 = new Symbol(); // TypeError
const sym3 = Symbol('hoge');
console.log(sym3.toString()); // Symbol(hoge)

シンボルはオブジェクトのプロパティのキーとして使用することができる。このことが重要で、シンボルの存在意義と言っても過言ではないかと思われる。

const sym = Symbol();
const obj = {};
obj[sym] = 'hoge';
console.log(obj[sym]); // hoge

列挙定数

シンボルには「一度生成されたシンボルは自身のみと等しい」という特徴があるため、次のように定数として表すことができる。

const EVN_LOGIN = Symbol( "event.login" );
const EVN_LOGOUT = Symbol( "event.logout" );

オブジェクトプロパティとしてのシンボル

シンボルをオブジェクトの特別なキープロパティとして使うこともできる。

const MEMBER = Symbol( "a" );
function save(value) {
  return save[MEMBER] = value;
}

シンボルをオブジェクトのキーにした場合、シンボルは Object.getOwnPropertyNames メソッドからは秘匿される。

var o = {
  foo: 42,
  [ Symbol( "bar" ) ]: "hello world",
  baz: true
};
Object.getOwnPropertyNames( o ); // [ "foo","baz" ]

しかし、次のメソッドを使用することでオブジェクトのシンボルプロパティを取得することができる。

Object.getOwnPropertySymbols( o ); // [ Symbol(bar) ]

Well Known Symbol

シンボル関数オブジェクトにあらかじめ定義されたシンボルのことを Well Known Symbol と呼ぶ。
たとえば、 iterate という Well Known Symbol は Symbol.iterate として参照可能である。これらは、JavaScript の組み込み関数の挙動をオーバーライドするために使用することができる。
また、これらを @@ プレフィックスを付けて呼ぶ(@@iterate)ことがある。

var arr = [4,5,6,7,8,9];
for (var v of arr) {
  console.log( v ); // 4 5 6 7 8 9
}
// for ... of ループの挙動を自作のイテレータでオーバーライド
arr[Symbol.iterator] = function*() {
  var idx = 1;
  do {
    yield this[idx];
  } while ((idx += 2) < this.length);
};
for (var v of arr) {
  console.log( v ); // 5 7 9
}
inserted by FC2 system