Javascripでオブジェクト指向

764 views

Published on

とりあえず、急ぎ足でまとめた。
ちょっと微妙なところがある。もうちっとうまくまとまるかも。
都度修正。

0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
764
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
6
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Javascripでオブジェクト指向

  1. 1. 1.JavaScriptでオブジェクト指向す。どっかエライ人に突っ込まれても俺は恐れない!
  2. 2. 2.まず、プロトタイプベースってなんやねん! プロトタイプベースってなんなのさ?一言でいってしまうと、既にインスタンスとして利用できる状態のものをベース(プロトタイプ) として用意してそいつに、 背びれ・尾びれをつけていくこと。 継承というよりまさに、【extend】拡張していくという言葉が ぴったしジャマイカ!!
  3. 3. 3.では、まずベースのインスタンスを用意しまっしょい! JavaScriptでオブジェクトを作るには? 一番簡単なオブジェクトは var obj = { }; ↑これ。 ・・・・・・・・。
  4. 4. 4.JavaScriptのオブジェクトは、他言語でいう連想配列 Javascriptでは、連想配列を var arrayObj = { obire : 尾びれだよ。 }; と記述できる。 これをオブジェクトリテラルと呼ぶよ。 実は、これがオブジェクトになる。 これをオブジェクト指向的に アクセスするには、 console.log(arrayObj. obire ); と書くことができるよ。
  5. 5. 5.ドット演算子でも配列的にでもアクセスすることもできる。 console.log(arrayObj. obire ); ↑の様にアクセスすることができれば また、以下の様にアクセスすることもできる。 console.log(arrayObj[ obire ]); ↑おなじみ連想配列的アクセス。 この、オブジェクトであり連想配列でもあるという 点は、javascriptの言語仕様なので そうなんだとおぼえるしかないちょ。
  6. 6. 6.ベースのインスタンスができたよ。 これに、尾びれ・背びれを色々つけたしていくよ。 javascriptで尾びれ・背びれをつけていくには ベースオブジェクトが必要。これは用意済み。 じゃあ、尾びれの付け方をみてみるよ。 var MainClass = function (){ };これは、javascriptで非常にベターなユーザー定義関数の 定義方法、これを関数リテラルと呼ぶよ。?オブジェクトに尾びれをつける(拡張する)のになぜ 関数を定義するんだい?
  7. 7. 7.オブジェクトの拡張(継承)には関数が必須条件。javascriptでオブジェクトを拡張するには、基本は ユーザーな定義関数が必要だよ。 ユーザーな定義関数が尾びれをつけるための 橋渡しをしてくれる。 といっても、普通の関数の使い方はしないよ。 関数コンストラクタ・・・・・ つまりカンストラクタを使うんだ!! と言ってもそんな違いはないよ。 このカンストラクタは、1000_VICKYの造語。
  8. 8. 8.とりあえずカンストラクタを使って拡張してみよう。 var MainClass = function (){ console.log( コンストラクタ ); }; まず、カンストラクタを作る。カンストラクタそのものは基本はユーザー定義関数と 同じ定義方法だよ。 ただreturnで値を返してはいけないよ。 そして、ここでMainClassという変数に無名関数が 代入されているわけだけど、javascriptだと 関数はオブジェクトなんだよね。 そう。関数オブジェクト。
  9. 9. 9.関数オブジェクト?関数がオブジェクト? 関数はオブジェクトなんだよ。だからね、 MainClass.addProperty = プロパティの動的追加 ;↑こんなことが出来る。これどういう動きをするのかというと console.log(MainClass.addProperty); ってすると「プロパティの動的追加」と出力される。 さらに、 MainClass(); とすると、もちろん関数としても実行される。
  10. 10. 10.関数オブジェクトは必ずprototypeプロパティを持つ。 関数はオブジェクトと前述した。 つまり、関数は一般的なオブジェクトと同一で プロパティを持つことができる。先に述べた addPropertyプロパティのように。 その関数オブジェクトは必ず【prototype】という プロパティを持つ。絶対にね。そう!ここで初めてプロトタイプベースのプロトタイプという キーワードが出現する。
  11. 11. 11.関数はオブジェクトを拡張するための橋渡し。少し前のページで僕は関数がオブジェクトを拡張するための 橋渡しをしてくれると言った。関数オブジェクトが必ず持っている【prototype】プロパティが まさにその橋渡し。 ここに、ベースとなるオブジェクト・・・つまり プロトタイプオブジェクトを代入してやる。 MainClass.prototype = { obire : 尾びれだよ。 }; としてやる。 ここでベースとなるオブジェクトがセットされた。
  12. 12. 12.中休み。ちょっとまとめるね。①まず、ベースのオブジェクトをつくるよ。var arrayObj = { obire : 尾びれだよ。 };②関数がオブジェクト拡張の橋渡しをするよ。 var MainClass = function() { console.log( コンストラクタ ); }; ③prototypeプロパティをセットするよ。 MainClass.prototype =arrayObj; とりあえずこの三点でオブジェクト拡張の 準備はできたよ。
  13. 13. 13.プロトタイプベースでもnewキーワードは存在する。オブジェクトを拡張するのに関数を使う際にちょっと変わった 使い方をするといった。 そう、関数をコンストラクタとして使う。 var subObj = new MainClass(); お? これはよくあるクラスベースのオブエジェクト生成方法だね。この時【subObj】という変数には関数オブジェクトMainClassを 通じて【arrayObj】というオブジェクトのプロパティを 持ったオブジェクトの参照が代入される。
  14. 14. 14.新たにできたオブジェクトは? 新たに生成されたオブジェクト【subObj】はプロトタイプのオブジェクト【arrayObj】を継承する。 つまり console.log(subObj. obire ); とアクセスすると【尾びれだよ】と出力される。関数オブジェクトを通じてプロトタイプオブジェクトを 元に拡張オブジェクトを生成できたわけだ。 ・・・・・・・・・・・・ 拡張してなくね?
  15. 15. 15.javascriptは動的だからいつでも拡張できる。 新たに生成されたオブジェクト【subObj】はただプロトタイプオブジェクト【arrayObj】をそのまま 引き継いだだけで一切拡張が行われていない。 が、javascriptは動的なのでいつでもプロパティを 追加することができる。 subObj.subProperty = 拡張後追加プロパティ ; 等とすると console.log(subObj.subProperty); とすると追加した値を参照できる。
  16. 16. 16.関数コンストラクタは実はオブジェクト初期化式 とは言え、拡張後のオブジェクトに動的にプロパティを追加していくのはちょっと手間なので、すこし効率を上げてみる。 var MainClass =function (){ this.sebire = 背びれだよ ; this.message = 大量だぜおい!!! ; }; とこんな風にしてみる。 そう、関数コンストラクタはまさにコンストラクター。 オブジェクトの初期化を行なってくれる。
  17. 17. 17.もう一度、newしよう。 var subObj = new MainClass(); 今度の【subObj】には元々のベースにあるプロトタイプオブジェクトと関数コンストラクタ内で記述した 初期化の内容が反映されている。つまり console.log(subObj.sebire); //=> 背びれだよ console.log(subObj.message); //=> 大量だぜおい!!! が出力される。
  18. 18. 18.拡張方法は、2通り。 前頁より、特定のオブジェクトをベースに、 拡張したオブジェクトを作成するためには関数コンストラクタの中に初期化式として記述するか。 あるいは、生成後のオブジェクトに直接動的に プロパティを追加してくか。の2通りが存在する。 おそらく基本は前者、一般的なクラスベース見たく拡張できるのでその方が、プロトタイプベースといえど 扱いやすいと思う。 そして、後者のように動的に追加したプロパティを
  19. 19. 19.javascriptにおけるオーバーライド。 javascriptでの継承において オーバーライドはどのような仕様なのか? 先ほど、拡張したオブジェクト【subObj】の subObj.obire = あ!尾びれじゃねえ、エラだった ;上記の様に代入する(オーバーライド)とするとどうなる? console.log(subObj.obire); //=> あ!尾びれじゃねえ、エラだった と出力される。 が、継承元のオブジェクト・・つまり【arrayObj】は
  20. 20. 20.継承もとのベースオブジェクトは読み出し専用。 javascriptでの継承において オーバーライドは常に上書きされる。 しかし、その場合ベースのプロトタイプオブジェクトは 変更が反映されず、オーバーライドを行ったオブジェクトそのものに、独自プロパティとして新たに同名のプロパティが 追加される。つまりこの場合、【subObj】には【obire】というプロパティが 正確には2つ存在することになる。【尾びれだよ】という値と【あ!尾びれじゃねえ、エラだった】
  21. 21. 21.独自プロパティとプロトタイプオブジェクトのプロパティ。 もし、独自プロパティと継承したprototypeプロパテイに 同名のプロパティが存在するような状態になった場合、 オブジェクトは独自プロパティを優先する。 このような状態はおそらくプロパティをオーバライドした 状態だろうが、このオーバライドな状態を解消したい場合 javascriptでは【delete】演算子を用いる。この場合、subObj.obireを元のプロトタイプオブジェクトの値に 戻したい時は delete ( subObj.obire);
  22. 22. 22.delete 演算子はオブジェクトのプロパティを削除する。 delete ( subObj.obire);という記述をしてやることで【subObj】の独自プロパティを 削除することになり、結果【subObj.obire】は当初のプロトタイプオブジェクトの値を参照するようになる。 ただし、この場合 継承元のプロトタイプオブジェクトから引き継いだものは 削除することはできない。
  23. 23. 23.総まとめだよ。 ①javascriptのオブジェクトは連想配列と同義だよ。 var arrayObj = { key_01 : value_01 }; console.log(arrayObj.key_01); console.log(arrayObj[ key_01 ]); の二通りの参照方法があるよ。②プロトタイプ継承を行うためにはベースのオブジェクトが必要。そのためには、関数を関数コンストラクタとして用いることで特定のオブジェクトを元に拡張オブジェクトを作成できるよ。 var MainClass = function(){ this.addProperty = 拡張プロパテイ ;
  24. 24. 24.総まとめだよ。 ③関数はオブジェクトだよ。関数オブジェクトは必ず prototypeプロパティを持つ。このprototypeオブジェクトに 代入した任意のオブジェクトが ベースのオブジェクトになるよ。 MainClass.prototype =arrayObj; ④new キーワードで新たな拡張オブジェクトを作成する。 var subObj = new MainClass();このオブジェクト【subObj】は、プロトタイプオブジェクトから 継承した【key_01】とコンストラクタ内に記述した
  25. 25. 25.関数オブジェクトのクラスは? 以上、プロトタイプ継承をざっくりまとめたよ。 ところで、僕は関数をオブジェクトだと言った。 先ほど、subObjというオブジェジェクトがMainClass関数というコンストラクタから生成されたように 関数も、とあるコンストラクタから生成される。 それが 【Function】関数コンストラクタだよ。
  26. 26. 26.Functionコンストラクタとは? その名の通り関数オブエジェクトを作るための 関数コンストラクタ。javascriptは内部的にこのFunctionコンストラクタを用いて 関数定義を行なっていると思って良い。 例えば、 function TestClass(){} も var TestClass = function(){}も内部でFunctionコンストラクタを呼んでいると思ってよい。
  27. 27. 27.Functionコンストラクタをnewすることもできる。 もちろんFunctionコンストラクタをnewすることによって 関数オブジェクトを作ることができる。例えば。var TestClass = new Function( a , b , console.log(a + b));というようにこの場合、TestClassという関数オブジェクトが 生成されることになる。・・・・・・・・・・・・Functionがnewできるということは Functionも関数なわけだ。 関数はオブジェクト。 Function も関数・・・・・・・・・・・・?
  28. 28. 28.Functionは関数オブジェクトだよ! Functionがコンストラクタとして呼べるということは Functionも関数オブジェクトなんだ!・・・ん?でも関数オブジェクトってFunctionをnewした結果 その返り値が関数オブジェクトなわけだろ? どうなってるんだ!?と悩んでもしょうがない!Function関数は、関数オブジェクトを 生成するが、Function関数そのものも関数オブジェクトだ。 これは言語仕様としてそう理解するしかない。
  29. 29. 29.Function関数のprototypeプロパティって。前に、僕は関数オブジェクトは【prototype】というプロパティを 必ず持つと述べた。Function関数も例外なく【prototype】というプロパティを持つ。 prototypeプロパティとはいったい何だっただろうか? ↓ そのprototypeプロパティを持つ関数コンストラクタによって生成されるオブジェクトのベースとなるオブジェクトを代入する プロパティだったね。
  30. 30. 30.Function関数のprototypeプロパティは関数オブジェクトのベース Function関数のprototypeプロパティは、一般の 関数オブジェクトの元になるオブジェクトなんだ。 つまり、Function.prototypeにプロパティを更に 追加することによってその他の関数オブジェクトにも 反映させることができるんだ。 例を見てみよう。 Function . prototype . addProperty = 追加プロパティ ; var TestClass = function (){ console.log( コンストラクタ );}; と、したとしようか。
  31. 31. 31.Function関数のprototypeプロパティは 関数オブジェクトに反映される。 Function . prototype . addProperty = 追加プロパティ ;var TestClass = function (){ console.log( コンストラクタ );}; 関数オブジェクトはFunction.prototypeを継承するのでこの場合、生成されたTestClassもaddPropertyプロパティを 持つことになる。試してみよう。 console.log(TestClass.addProperty); // => 追加プロパティ と出力される。
  32. 32. 32.Function . A とFunction .prototype . Aは同一。 ちょっと、ややこしいが関数オブジェクトはFunctionクラスの インスタンスだと言った。 関数オブジェクトを生成する方法は複数あるがクラスベースで 擬似的に考えた場合、Function関数をnewして生成された関数オブジェクトはFunction . prototypeを継承することになる。 これは例えば、MainClass関数をnewした場合、生成されたオブジェクトがMainClass.prototypeを継承することと同義だ。 関数オブジェクトがFunction.prototypeを継承するなら Function関数そのものはどうなるのだろうか?
  33. 33. 33.Function . A == Function .prototype . Aな関係。たとえば、Function.prototype. A= A ;としたとする。 この処理は関数オブジェクトに反映される。つまりFunctionという関数オブジェクトにも反映される。 console.log(Function.prototype.A); とすると【A】が出力される。さらに、 console.log(Function.A); としても【A】が出力される。 ちょっと自己参照な実装がされているようだ。 Functionクラスのちょっと変わった一面だったね。
  34. 34. 34.自分用最後の大まとめ。①javascriptのオブジェクト生成は複数ある。 ここではオブジェクトリテラルで生成してみよう。 var arrayObj = { key01 : value01 , key02 : value02 } これが、これから作成するインスタンスの原型となる プロトタイプオブジェクトである。②これを継承するクラスを作成する。 var MainClass = function (){ this.only = 独自プロパティ ; }
  35. 35. 34.自分用最後の大まとめ。③生成した関数オブジェクトにprototypeプロパティを指定する。 関数オブジェクトは必ずprototypeプロパティを所持している。 //先ほど作ったオブジェクトリテラルを代入する。 MainClass.prototype = arrayObj;④MainClassクラスのインスタンスを生成する。 var subObj = new MainClass(); //継承したプロパティ console.log(subObj.key01); console.log(subObj.key02);
  36. 36. 34.自分用最後の大まとめ。⑤もちろん独自プロパティも保持してる。 console.log(subObj.only);⑥そして、この時オブジェクトsubObjのプロトタイプオブジェクトは MainClass.prototypeであると言える。⑦MainClassなどの関数オブジェクトは Functionクラスのインスタンスである。 つまり、関数オブジェクトMainClassのプロトタイプオブジェクトは Function.prototypeであるといえる。
  37. 37. 34.自分用最後の大まとめ。⑧Function関数はFunctionクラスのインスタンスでもある。 つまり、Function関数オブジェクトそのものの プロトタイプオブジェクトもFunction.prototypeであるといえる。⑨Function.prototypeが保持するオブジェクトは Functionも保持する。つまり以下のような現象がおきる。 Function . prototype . addProperty = Function追加 ; とすると console.log(Function . addProperty); //=> Function追加  が出力される。
  38. 38. 34.自分用最後の大まとめ。 終劇

×