LOG

Symbol

ES6で追加された新しいプリミティブ値Symbolのメモ

参考
Symbol – JavaScript | MDN

Symbolとは

ECMA Script6で追加された新しいプリミティブ値で、一意のプリミティブ値を作成します。
作成時にラベル(description:説明)を渡す事ができます。

let mySymbol = new Symbol();
// -> Uncaught TypeError: Symbol is not a constructor

let mySymbol = Symbol();

// -------------------------------
// ラベルを渡す
let mySymbol = Symbol('name');
console.log(mySymbol === mySymbol);
// -> true
console.log(mySymbol === Symbol('name'));
// -> false
console.log(Symbol('name') === Symbol('name'));
// -> false

また、ES6からプリミティブ型の明示的なラッパーオブジェクトの作成はサポートされなくなった為、Symbolをnewすることは出来ません。
※ 既存のプリミティブ型はまだ出来ます。new Stringとか

もしSymbolオブジェクトのラッパーオブジェクトを作成したければ、Object()関数を利用します。

let mySymbol = Object(Symbol("name"));
console.log(mySymbol, typeof mySymbol);
// -> Symbol{} "object"

Symbol.for()

Symbol.forを使うと全体で使えるシンボルレジストリ内に対して検索、生成をします。

Symbol.for('name');

でSymbol(name)がシンボルレジストリ内にあればそれを返し、無ければシンボルレジストリ内に生成します。

let local  = Symbol('local symbol');
let global = Symbol.for('global symbol');

console.log(local === Symbol('local symbol'));
// -> false

console.log(global === Symbol.for('global symbol'));
// -> true
console.log(Symbol.for('global symbol') === Symbol.for('global symbol'));
// -> true

console.log(global);
// -> symbol(global)
console.log(Symbol.keyFor(global));
// -> global symbol

プライベートっぽいメソッドやメンバを作成する

Symbolを使い、外部から直接参照されにくいメソッドやメンバを作成します。
Object.getOwnPropertySymbolsでSymbolが出てきてしまうので完全にプライベートな状態は作れない。
※ Object.keysやfor…in構文では無視される。

// クラスの作成
// ---------------------------------------------
// myClass.js
// ---------------------------------------------
const firstName  = Symbol('first name');
const secondName = Symbol('second name');

export default class MyClass{
    constructor(fname,sname){
        this[firstName]  = fname;
        this[secondName] = sname;
    }
    get fullName(){
        return `${this[firstName]} ${this[secondName]}`;
    }
}

// ---------------------------------------------
// script.js
// ---------------------------------------------
import MyClass from './myClass.js';

let myClass = new MyClass('Kenji','Yokota');
console.log(myClass.fullName);
// -> "Kenji Yokota"

console.log(Symbol('first name'));
// -> undefined

console.log(Object.getOwnPropertySymbols(myClass));
// -> [Symbol(first name), Symbol(second name)]

/(^o^)\

build-in Symbol

最初から持ってる特別なSymbol

Symbol.iterator

参考
Symbol.iterator – JavaScript | MDN

イテレータを定義したり出来る

let obj = {
    a : 'Yokota Kenji',
    b : 28,
    c : 'male'
}
obj[Symbol.iterator] = function* (){
    let index = 0;
    let obj   = Object.keys(this);
    while(index < obj.length){
        yield this[obj[index]];
        index++;
    }
}

for(let val of obj){
    console.log(val);
}
// -> Yokota Kenji
// -> 28
// -> male

Array iteratorを返す

let obj = {
    a : 'Yokota Kenji',
    b : 28,
    c : 'male'
    [Symbol.iterator](){
        return Object.keys(this).values()
    }
}

for(let val of obj){
    console.log(val);
}
// -> Yokota Kenji
// -> 28
// -> male