速習ECMAScript2018を勉強する Symbol編

Symbol シンボル

  • これも新しいタイプです。 一般的に定数の値として使われたりします。
const TOMODA = 'TOMODA';
const HAMADA = 0;
const YASUDA = Symbol();
const SUZUKI = Symbol();
  • 定数を作るのに、右の値は意味がありません。 そのため代わりにシンボルを設定することで、代行できます。
  • JS には、外からアクセスを禁止する,プライベート命令がありません。 詳しい理論はわかりませんが、シンボルを使うと外からのアクセスに制限をかけることができるみたいです。 これは明示的に アンダーバーから始まる文字は、プライベートだから外からアクセスしないでという規則よりも,より直接的な制限です。

  • 簡単な制限のかけ方は、fileを分けて、呼び出し側からはプライベートなプロパティにアクセスが為難いようにすることです。

  • MyApp.js

const SECRET = Symbol()

// export class MyApp {
module.exports = class MyApp {
  constructor(secret) {
    this.data1 = 1;
    this['data2'] = 2;
    this[SECRET] = secret;
  }
  checkSecret(secret) {
    return this[SECRET] === secret;
  }
}
  • index.js
const MyApp = require('./MyApp')
// import { MyApp } from './MyApp'

let c = new MyApp();
console.log(c.checkSecret())
console.log(c.data1)
console.log(c['data2'])
console.log(c[SECRET])
  • index.js側から実行すると、下記の結果になります。
$ node index.js
true
1
2
undefined
  • シンボルのプロパティには、直接アクセスできていないことがわかります。専用メソッドを使えばアクセスできてしまいますが、これで大部分はOKじゃないかと思います。

  • あとコメントにしているimport は、まだNode環境では使えません、import の方がrequireよりも便利な場面が多いので、webpack等を使えるのであれば、そちらを使ったほうがいいかもしれません。

  • webpackは、ファイルを纏めるためのものであるので、逆に言うと纏めるコマンドが余計にかかりますので、試すだけならば、requireでするほうが、手間がかかりません。
  • Nodeの偉い方が、そのうちimportもサポートしてくれると思うので、その間は、両方使えるようにしておくしかないです。
  • 次にプロパティが制限できるなら、メソッドも制限ができそうです。

  • MyApp2.js

const SEC_METHOD = Symbol();

module.exports = class MyApp2 {
  [SEC_METHOD]() {
    return 'Private Value';
  }
  getSecret() {
    return `Public: ${this[SEC_METHOD]()}`
  }
}
  • index.js
const MyApp2 = require('./MyApp2')

let c = new MyApp2();
console.log(c.getSecret())
// console.log(c[SEC_METHOD]())
  • 下記が実行結果です。
    • 通常のメソッドから呼びした場合はアクセスできていますが、コメント部分を実行させると関数が見つからないとエラーになることがわかります。
$ node index.js
Public: Private Value
  • シンボルを使うと、挙動が変わることがありますが、そのときは使うのをやめるか、原因を突き止めて対応すればいいので、使わない手はないと思います。