TypeScriptのprivate表現

はじめに

昔TypeScriptのprivateって、頑張って出力されるJavaScriptでもprivateな状態になるような気がするんだが、今はprivateもpublicもjsで見ると同じだなぁと思い、真面目に調べてみた。

typescript

module Fuga {
	class Hoge {
		public a = 0;
		private b = 0;
		public static c = 0;
		private static d = 0;
		public A() {}
		private B() {}
		public static C() {}
		private static D() {}
	}
}

typescript 0.8.0で出る javascript

var Fuga;
(function (Fuga) {
    var Hoge = (function () {
        function Hoge() {
            this.a = 0;
            this.b = 0;
        }
        Hoge.c = 0;
        Hoge.d = 0;
        Hoge.prototype.A = function () {
        };
        Hoge.prototype.B = function () {
        };
        Hoge.C = function C() {
        }
        Hoge.D = function D() {
        }
        return Hoge;
    })();    
})(Fuga || (Fuga = {}));

jsレベルで見ればすべて同じで、publicアクセスが出来る。

typescript 0.9.0で出る javascript

var Fuga;
(function (Fuga) {
    var Hoge = (function () {
        function Hoge() {
            this.a = 0;
            this.b = 0;
        }
        Hoge.prototype.A = function () {
        };
        Hoge.prototype.B = function () {
        };
        Hoge.C = function () {
        };
        Hoge.D = function () {
        };
        Hoge.c = 0;
        Hoge.d = 0;
        return Hoge;
    })();
})(Fuga || (Fuga = {}));

こちらもjsレベルで見ればすべてpublicアクセスが出来る。違いはstatic変数が下に行った事くらい。
以後、npmでお手軽に入る1.0.0、1.1.0-1、1.3.0、1.4.1で出してもすべて同じ。

結論

TypeScriptのprivateはJavaScriptレベルではpublicと一緒。
ちなみに省略したけどprotectedもしかり。


俺が昔違ってた気がすると思ってたのは気のせいだったのかも。
ちなみに、一応これも試したけど全部同じ。

constructor(private e: number) {}

moduleによるprivate

ちなみにさっきのjavascriptで実は一個private表現が混ざっている。
Hogeクラスそのものだ。
FugaモジュールでラップされててHogeクラスがexportされてないので、JavaScriptで外部からこのHogeにアクセスする方法はない。


Hogeをただのclassではなくexport class Hogeとすると、

    Fuga.Hoge = Hoge;

という一行がJavaScriptに追加され、Fuga.Hogeでアクセスできるようになる。
ので、module内のexportしないものは少なくともmodule privateなので、JavaScritでのprivate表現をTypeScriptでやるなら、classでやるんじゃなくてmoduleでやるのがいいのかなと。

補足: JavaScriptによるprivate表現について

これは解説しているところがたくさんあるんで適当に拾ってみてもらえれば。
例えばここでいう「A. 紳士協定」はただ接頭語として_を付与しているんだが、
http://blog.tojiru.net/article/238901975.html
これ以外のJavaScript private表現は非常に苦しい。prototypeを諦める、が一番よく使われるし実装も素直なんだが、prototypeに一個入れておけばいいものをすべてインスタンスに持つ事になるので大変メモリ効率が悪い。


で、昔はそういう頑張ったJavaScriptをTypeScriptが吐いていた気がして、このプロジェクトではprivate禁止ねーと声高に言っていたんだが、記憶違いだったのかTypeScriptはスコープはTypeScriptの世界だけの話と割り切っているようでした、と。
うーん間違えてましたお恥ずかしい。


しかしprivateとpublicがJavaScriptで全く識別できないというのも、TypeScriptお前はそれでいいのかという感が若干あるんだけども。