◆ くろーじゃ

// static 変数 var f = function(){ var static_var = 0 return function(){ console.log("static_var : ", static_var++) } }()
f() static_var : 0 f() static_var : 1 f() static_var : 2 f() static_var : 3

何度関数実行しても 前の値が残っているのでstatic変数ですね
closureの基本です

// ここからクラスのようなもののprivate・static変数の作り方 A = function(){ var private_static_var = 0 return function(){ var private_var = 0 this.public = 0 this.method = function(){ console.log("method: private_var", private_var++); console.log("method: private_static_var", private_static_var++); } this.method_s = function(){ var static_var = 0; return function(){ console.log("method_s: static_var", static_var++); } }() this.clear_private_var = function(){ private_var = 0 } this.clear_private_static_var = function(){ private_static_var = 0 } } }() // static メソッド A.static_method = function(){ console.log("static_method") } // staticメソッドにstatic変数 A.static_method_s = function(){ var static_var = 0 return function(){ console.log("static_method_s: static_var: ", static_var++) } }() // 普通のメソッド A.prototype.normal_method = function(x){ console.log("normal_method"); } // 普通のメソッドにstatic変数 A.prototype.normal_method_s = function(x){ var static_var = 0 return function(){ console.log("static_method: static_var: ", static_var++) } }()

JavaScriptで正しいstaticメソッドの書き方がわからないですが クラスある言語だと A::static_method(); といった使い方なので A.static_method(); と書けるようにしてみました

var a = new A var b = new A a.normal_method() normal_method a.normal_method_s() static_method: static_var: 0 a.normal_method_s() static_method: static_var: 1 a.normal_method_s() static_method: static_var: 2 b.normal_method() normal_method b.normal_method_s() static_method: static_var: 3 b.normal_method_s() static_method: static_var: 4 b.normal_method_s() static_method: static_var: 5 a.constructor.static_method() static_method a.constructor.static_method_s() static_method_s: static_var: 0 a.constructor.static_method_s() static_method_s: static_var: 1 a.constructor.static_method_s() static_method_s: static_var: 2 a.constructor.static_method_s() static_method_s: static_var: 3 a.constructor.static_method_s() static_method_s: static_var: 4 b.constructor.static_method() static_method b.constructor.static_method_s() static_method_s: static_var: 5 b.constructor.static_method_s() static_method_s: static_var: 6 b.constructor.static_method_s() static_method_s: static_var: 7 b.constructor.static_method_s() static_method_s: static_var: 8 a.method() method: private_var 0 method: private_static_var 0 a.method() method: private_var 1 method: private_static_var 1 a.method() method: private_var 2 method: private_static_var 2 a.method() method: private_var 3 method: private_static_var 3 b.method() method: private_var 0 method: private_static_var 4 b.method() method: private_var 1 method: private_static_var 5 b.method() method: private_var 2 method: private_static_var 6 b.method() method: private_var 3 method: private_static_var 7 b.clear_private_var() b.method() method: private_var 0 method: private_static_var 8 b.clear_private_static_var() b.method() method: private_var 1 method: private_static_var 0 a.method() method: private_var 4 method: private_static_var 1 a.method_s() method_s: static_var 0 a.method_s() method_s: static_var 1 a.method_s() method_s: static_var 2 b.method_s() method_s: static_var 0 b.method_s() method_s: static_var 1 b.method_s() method_s: static_var 2

_s がついた関数(メソッド)はその関数のstatic変数をインクリメントして表示してます
normal_methodは 普通にprototypeにあるメソッドです
どのインスタンスからも同じ関数が呼ばれるので共有されています

static_methodはconstructorを通して呼んでます
これもインスタンス間で共有になります

methodはprototype通さないでインスタンスのプロパティに関数を入れたものです
private変数とprivate+static変数があります
privateはインスタンスごとにデータが保存され private+staticはインスタンス間で共有になります
constructorになる関数を作成時にthis.xxx形式で作ったメソッドだけで使えるprivate変数です(closureですので)
clear_private_varclear_private_static_varでアクセスできてます
method_sの方はただの メソッドのstatic変数です
// prototype使ったメソッドでも共有できるprivateメソッドの作り方 function B(){ } B.prototype = function(){ var private_var = 10 var private_method = function(){ console.log("private_method: private_var: ", private_var++) } var private_method_2 = function(){ console.log("private_method: private_var: ", private_var++) } var private_method_s = function(){ var static_var = 1 return function(){ console.log("private_method_s: static_var: ", static_var++) } }() return { private_method: private_method, private_method_2: private_method_2, private_method_s: private_method_s, constructor: B } }() Object.defineProperty(B.prototype, "constructor", {enumerable:false})
x = new B y = new B x.private_method() private_method: private_var: 10 x.private_method() private_method: private_var: 11 y.private_method() private_method: private_var: 12 y.private_method() private_method: private_var: 13 x.private_method_2() private_method: private_var: 14 x.private_method_2() private_method: private_var: 15 y.private_method_2() private_method: private_var: 16 y.private_method_2() private_method: private_var: 17 x.private_method_s() private_method_s: static_var: 1 x.private_method_s() private_method_s: static_var: 2 x.private_method_s() private_method_s: static_var: 3 y.private_method_s() private_method_s: static_var: 4 y.private_method_s() private_method_s: static_var: 5 y.private_method_s() private_method_s: static_var: 6

この方法では prototypeにある以上共有されるのでインスタンスごとに別の値は持てないです
インスタンスごとに値をもつprivate変数は上のAの方法でやらないと無理そうです

最後のObject.defineProperty(/*略*/)を書いてる理由はココを参考に

staticはいいのですが privateになるとclosureの都合で別のところで定義されたメソッドから見れないという不都合が出てきます
他の言語みたいなprivateを使いたいならBの方法でまとめてメソッド定義するしかなさそうです