JavaScriptで、プライベートな値の保管方法について
解決したいこと
以下の3つの条件を満たせるような、JavaScriptのインスタンスに紐づく値の保管方法は、自分が提示した以外にないでしょうか。
-
prototypeからもアクセスできる(必須)…元のコードがnew以外で生成したオブジェクトのプロトタイプを差し替えるなど黒魔術満載のものなので、その枠内で動くものでないといけない状況です。 - プライベートな値とする(できれば)…インスタンス、クロージャ、モジュールなど何かしらの単位で値を封じきって、第三者に値の参照・書き換えなどをさせないようにできる
- 超高速(できれば)…モジュール内に
WeakMapを置く方法を取っていたところ、WeakMap#getで律速してしまっていました。これより速い処理が可能であれば行いたいところです。
なお、実行環境としては各ブラウザ(Chrome、Safari、Firefox、Edge)の最新版を前提とします。
自分で試した・調査したこと
以下の手法について調査・あるいは実装してみました。
ES7のプライベートプロパティ(#prop)
言語純正の機能でありアクセス権は完璧、オーバーヘッドも薄そうですが、classでしか使えない以上、今回の条件では使えないです。
WeakMap
WeakMapのインスタンスをモジュールローカルにしてしまえばモジュール外からのアクセスは不可能となるのですが、WeakMap#getで書いたコードが、通常のプロパティ参照を行うコードの5分の1ぐらいしか速度が出ず、なんとかならないかと思ったのが今回の質問に至った動機です。
普通のプロパティに保管する
速度的には最速なのですが、もちろん外部からも参照できてしまいます。
シンボルプロパティ
モジュール独自のシンボルを作成して、それをキーにしたプロパティに格納すれば、不意に衝突する可能性もありませんし、Object.keysなどにも登場しません。ただし、Object.getOwnPropertySymbolsでアクセスできるので、完璧ではありません。
クロージャ
クロージャで封じきる、という手段も考えたのですが、当該プロパティを使うメソッドが数十個あるような状況で、メソッドをコピーするコストも半端なさそうなので、あまり現実的な選択肢ではありません。