JavaScriptのオブジェクト指向プログラミング

2pt

で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/2007/02/13/javascri...
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を使っているかどうかがわかる

「JavaScriptのオブジェクト指向プログラミング」について友人に書いてもらう。

あなたにとって「JavaScriptのオブジェクト指向プログラミング」とは?

ログインするとワンクリックでキーワードを投稿できます

ログインする 新規登録する

お気に入りの説明

0 pt
Ajax なページを作るときに、めんどくさがって手続き型で JavaScript を組んでいると、いつもオブジェクト指向で組んでおけばよかったと後悔する。 クロージャ の理解がミソだと思う。 最近、組ん...
もっと読む

関連したキーワードを持つお気に入り

他の人の「JavaScriptのオブジェクト指向プログラミング」を見る