JavaScriptではコンストラクタをfunctionで定義したりprototypeにメソッドを登録したりとやや癖のある方法ではありますが、下記のようにクラスを定義できます。
sample.js
function MyClass(prop) { // コンストラクタ
this.prop = prop;
}
// var MyClass = function(prop){ // としても同じです
// this.prop = prop;
// };
MyClass.CONST = 128; // クラス定数
MyClass.classMethod = function(x) { // クラスメソッド
return x*x;
};
MyClass.prototype.method = function(x) { // メソッド
return x+x;
};
// MyClass.prototype = { // メソッド数が多い場合は以下の記法が役立ちます
// method: function(x) {
// return x+x;
// },
// method2: function(x) {
// return x+x;
// }
// };
// インスタンス
var obj = new MyClass(1.0);
console.log(obj.prop);
console.log(obj.method(512));
// クラス
console.log(MyClass.CONST);
console.log(MyClass.classMethod(12));
実行例
$ node sample.js
1
1024
128
144
一見自然に見えますが、インスタンスメソッドを下記のようにコンストラクタに含めて定義するとインスタンス毎にメソッドのためにメモリが確保され、動作はしますが非効率です。
sample.js
function MyClass(prop) { // コンストラクタ
this.prop = prop;
this.method = function(x) { // メソッド
return x+x;
}
}
// インスタンス
var obj = new MyClass(1.0);
console.log(obj.prop);
console.log(obj.method(512));
実行例
$ node sample.js
1
1024
最初のsample.jsのように、prototypeという参照で、特殊な共有オブジェクトに関数定義を保存することで上記問題を回避できます。
クロージャを利用してプライベートメンバを実現できます。prototypeで関数定義を共有しないことがポイントです。
sample.js
function MyClass(prop) {
this.getProp = function() {return prop;}
}
var obj1 = new MyClass(1);
var obj2 = new MyClass(2);
console.log(obj1.getProp());
console.log(obj2.getProp());
実行例
$ node sample.js
1
2
空のオブジェクトは名前空間として利用できます。
var NameSpaceA = function(){};
var NameSpaceB = function(){};
NameSpaceA.MyClass = function(prop){
this.prop = prop;
};
NameSpaceB.MyClass = function(prop){
this.prop = prop;
};
NameSpaceA.MyClass.prototype.method = function(){
return '[NameSpaceA::MyClass] ' + this.prop;
};
NameSpaceB.MyClass.prototype.method = function(){
return '[NameSpaceB::MyClass] ' + this.prop;
};
var objA = new NameSpaceA.MyClass('a');
var objB = new NameSpaceB.MyClass('b');
console.log(objA.method()); //=> [NameSpaceA::MyClass] a
console.log(objB.method()); //=> [NameSpaceB::MyClass] b