なんでprivateなインスタンスメソッドの中でthis使えないの?
var A = function(){
var hoge = function(){
console.log(this, " in Private");
}
this.moge = function(){
console.log(this, " in Privileged");
hoge();
}
}
var obj = new A();
obj.moge();
return;
実行すると
Object in Privileged
Window test.html in Private
こうなりました。
あーそうか、関数呼ぶときは{object}.{method}にしないとだめなんだ。そうしないと暗黙的にグローバルオブジェクトwindowが使われるのか。
いやまて、どっちにしろオブジェクト「A」はメソッド「hoge」を持ってるわけなくて、存在しているのはコンストラクタのスコープの中だけか。
function(){} の中身は別のスコープになるんだけど、呼び出す側によって、コンテキスト(何がthisか)を変更できる。
hoge()
のように、オブジェクトを指定しなければ、どんな場所でもコンテキストにグローバルオブジェクトが使われ
obj.hoge()
とすると、objのコンテキストでhoge()が実行される。
スコープとコンテキスト混同してたわ。
こうすると使えるようになります。
var A = function(){
var hoge = function(){
console.log(this, " in Private");
}
this.moge = function(){
console.log(this, " in Privileged");
hoge.call(this);
}
}
var obj = new A();
obj.moge();
return;
Object in Privileged
Object in Private
カプセル化まとめ
privateなメソッドの中でthisできないの知らなくてちょっとはまった…。call, applyで呼べるっちゃ呼べるけどどうなんだろ…。
privateメソッドっていうよりクロージャって呼んだ方がよくね?
// コンストラクタ
var Human = function(name, called){
// private member
// - このスコープでのみアクセス可能
var happy = false;
// public member
// - いつでもアクセス可能
this.name = name;
// private method
// - 単なるクロージャ
// - 普通に呼び出すとグローバルコンテキストで実行される。
// callしない限りこのオブジェクトでのthisが使えない
// - private memberのみアクセスできる
var format = function(){
return name + ', "' + called + '"';
}
// privileged method
// - privateにもpublicにもアクセスできる
this.makeHappy = function(){
happy = true;
};
this.isHappy = function(){
return happy;
}
this.toString = function(){
return format();
}
};
// public method
// - privilegedにアクセスできる
// - privileged が定義されていればそちらが優先させる
Human.prototype.faith = function(num){
this.makeHappy();
};
var akkun = new Human('akkun', 'the sleeping drummer');
console.log(akkun.name);
console.log(akkun.toString());
console.log(akkun.isHappy());
akkun.faith();
console.log(akkun.isHappy());
console.log(akkun.format);
出力
akkun
akkun, "the sleeping drummer"
false
true
undefined
privileged method はprivateにもpublicにもアクセスできるなら、publicいらなくない?
http://blogs.msdn.com/kristoffer/archive/2...
prototypeで定義する方が速いです。
といっても差がでるのは万単位でnewする場合だけど。
privateやprivilegedにすると、newするたびに、関数の中が実行される。メソッドなども再定義される。
のでメモリを食う。生成に時間もかかる。
publicなインスタンス変数はprototypeで定義するのではない
インスタンスメソッドがprototypeで定義するんだったら、インスタンス変数もそうなんだろうと勝手に思い込んでこんなコードを書いた。
コード
var i = 0;
var Hoge = function(){
this.myprop.push(i++);
}
Hoge.prototype.myprop = [];
var hoge1 = new Hoge();
var hoge2 = new Hoge();
var hoge3 = new Hoge();
println(hoge1.myprop);
println(hoge2.myprop);
println(hoge3.myprop);
結果
0,1,2,3
0,1,2,3
0,1,2,3
おお、なんてこった。みごとに共有されている!
prototypeとは何かを理解していればこんなことにはならなかったかも…。自分自身に定義されてなければ、prototypeオブジェクトを参照する。
このコードの場合、自分にmypropが定義されていないので、prototypeの方を参照する。オブジェクト全てが同じprototypeのmypropを参照するのでこうなる。関数の場合は同じものを参照すればいいんだけど、変数は共通のものを使えない。結局コンストラクタ内でthisするしかない。
ちなみに、hasOwnPropertyしてみるとprototypeを使っているかどうかがわかる。