Posted at

ES2015 Classでprivateメソッドであることを表明する

More than 1 year has passed since last update.

ES2015 Classでprivateメソッドについて考えた結果、private-assertionというモジュールを作ってみたのでまとめ。


privateメソッド実現方法いろいろ

ES2015 Classでprivateメソッドってどうやって表現するの?と調べてみた。


Underscore

古き良きJavaScriptのようにメソッド名の先頭をアンダースコアにする。

class Hoge {

_inner() {
}
}

確かにわかりやすいっちゃわかりやすいんだけど、人間の手で守っていくしかない手法。というかクラスベースになったのにこんな書き方嫌だ!他にもクロージャー使う方法もあるけどそれも嫌だ!


Symbol/WeekMap

どうやら調べてみるとSymbolやWeekMapを使った実装が一般的?らしい。

JavaScriptのクラスでprivateを実現してみたかった人生だった

フィールドは簡単に定義できそうだけど、private methodの実装にはひと手間かかりそうだなという印象。

この記事にあるprivateメソッドの書き方ならそれほど手間なく書けそう。

Private Methods In JavaScript


TypeScriptを使う

いや本当にTypeScripts好きだし使えばいいと思うんだけど、プロジェクトによってはflowtypeだったりするよね。


Decoratorを使う

こう色々と調べてみると、classの書き方を損なうことなくprivateメソッドを書くのは難しい感じがする。それをどうにかできないかと考えて作ったのがprivate-assertion。decoratorを使っている。

privateメソッドにどうアクセスさせないか、ではなくprivateメソッドであることを表明して、外からアクセスされたら落とせばいいじゃんという発想。引数のチェックではないのでいわゆる表明プログラミングとはちょっと違うかもしれないけど、それに近い発想。

import privateAssertion from 'private-assertion';

class Hoge {
publicMethod() {
return this.privateMethod();
}

@privateAssertion
privateMethod() {
return 'call from private only';
}
}

const hoge = new Hoge();

hoge.privateMethod();
// => Error('Hoge#privateMethod is private method.')

privateMethodであることが明確であり、ES2015 classの構文を壊すことなく実装できるこういう書き方のほうが好み。ただ「stacktraceたどればprivate callか判定できるんじゃね?」という雑な考えで書いたので、うまく動かないパターンは普通にありそう...(書きながら、たぶん継承したら呼べてしまうことがわかったので直したい)。


標準化を待つ

private methodのproposalは出てるので早く標準化されるといいですね。

https://github.com/tc39/proposal-private-fields/blob/master/METHODS.md