最近JavaScriptを触り初めてまず驚いたのが、
CやC#とクラスやらコンストラクタやらがなんか違う!という部分でした。
実際何がどう違うのか、今日少し勉強したのでまとめてみます。
※間違ってる部分あるかもしれません。ビシバシ指摘いただけるとありがたいです。
まずクラスを作ってみる。
//C#
class test(){
}
//JavaScript
var Test = function(){};
私にとって馴染みのあるのは上の方なんですが、なんとJavaScriptでは
関数にクラスの役割を与えているらしいです。
だからこのTestクラスはちゃんとインスタンス化が可能です。
//JavaScript
var test = new Test();
メソッドはどうなってるの?
//C#
class test(){
public void cat(){
Console.Write("にゃーん");
}
}
//JavaScript
var test(){
this.getName = function(){
return "ミャオ";
}
}
メソッドっていうか、値が関数なだけでやん!プロパティですやん!って思いましたが、
JavaScriptではこれがメソッドを担っているらしいです。
コンストラクターでの定義以外に、あとからメソッドを追加することもできます。
//JavaScript
var Test = function(name){
this.name = name;
}
var test = new Test('irico');
test.intro = function(){
return this.name + 'です。';
}
console.log(test.intro()); //「iricoです。」と表示される
なので、同じクラスから作られたインスタンスでも、持っているメンバーが違う、ということがありえます。
他にもメンバーを削除(delete
)したり、削除や追加を行わないようにする (seal
)ことも可能です。
var Test = function(name){
this.name = name;
type = "fish";
}
var test = new Test('irico');
console.log(test.intro()); //iricoです。
delete test.intro; //削除
console.log(test.type); //こっちは残ったまま
Object.seal(this); //コンストラクターの末尾に追加すると保護される
コンストラクターを関数として呼べちゃう
関数をコンストラクターとして使っている以上。そのまま関数として使ってしまうことができます。
var Test = function(name){
this.name = name;
};
var test = Test('irico'); //直接呼び出し
console.log(test); //undefined
console.log(name); //irico
console.log(test.name); //エラー
use strictにしていると動かないので注意です。
これだとオブジェクトが生成されず、一行目は未定義になっていますね。
二行目はthisの為にグローバルオブジェクトから参照されています。
対策
関数として呼び出された場合は、thisがグローバルオブジェクトを示すので、それを逆手にとって、
thisがグローバルの時、コンストラクターを呼び出す、という解決方です。なるほど。
var Test = function(name){
if(!(this instanceof Test)){
return new Test(name);
}
this.name = name;
}
※「[改定新版]モダンスタイルによる基盤から現場での応用まで JavaScript本格入門」(著:山田祥寛)を参考に学習しました。