クラス -> 内部関数

Posted by muchag | JavaScript |
初回投稿:2015-02-28 (土) 0:27:09 | 最終更新:2015-02-28 (土) 0:38:35

内部関数は、ちょっと特殊みたい。

内部関数とは

クラス内に設置したローカルメソッド。
外部からは呼べない。

  1. var hoge = ( function() {
  2.  
  3.   // constructor
  4.   var hoge = function() {
  5.     this.x = 5;
  6.   };
  7.  
  8.   // 内部関数(クラス内メソッド)
  9.   function moge() {} ← これ
  10.  
  11.   var p = hoge.prototype;
  12.  
  13.   p.f1 = function() {
  14.     return true;
  15.   };
  16.  
  17.   return hoge;
  18. })();

 

呼び出し

コンストラクタからでも、公開メソッドからでも関数名(メソッド名)で呼び出せた。

  1. p.f2 = function() {
  2.     moge();
  3. };

 

特殊なところ
this

内部関数内では、this を使えない。
解決策は後述。
 

引数

引数があると、通常通りでは呼び出せなかった。

  1. function moge( arg ) {}
  2.  
  3. p.f2 = function() {
  4.     moge( arg );
  5. };

これでは、syntax error にはならないけど、値が渡らない。
 

解決策

上記2点を一度に解決。
(解決法はわかったけど、まだあまりよく理解できていない)

apply メソッド、または call メソッドを利用する。

つまり、下記のように呼び出す。

  1. function moge( arg ) {}
  2.  
  3. p.f2 = function() {
  4.     moge.apply( this, arg );
  5.     moge.call( this, arg );
  6. };

 

誰それ

参考サイトを見ると

callはFunction.prototypeの中にあります。

あと味:applyとcallの使い方を丁寧に説明してみる

と書いてあるので、プロパティ・オブジェクト からの呼び出しだから、というなのかもしれないけど、今はまだよくわかっていない。
 

this はどこへいった・・・

引数に指定した this。
でも、内部関数側は受け取っていない。

どうも、自動的に(強制的に?暗示的に?)受け取るらしく
これで、内部関数内で this を利用できる。

また、何も this を渡さなければいけないわけではなく
要は内部関数内で this と記述して利用したいオブジェクトを指定すればよいらしい。
 

両者の違いは?

apply

  1. var args = [ 1, 2, 3 ];
  2. moge.apply( this, args );

apply は、this 以外の引数を、配列にまとめて渡す。
本当に配列を渡すときとか、引数が多い時、または変更が頻繁にあるときなどには便利。
 
call

  1. moge.call( this, 1, 2, 3 );

call は、this 以外の引数を列挙して渡す。
 

参考サイト

あと味:applyとcallの使い方を丁寧に説明してみる

Posted by muchag | JavaScript |
初回投稿:2015-02-28 (土) 0:27:09 | 最終更新:2015-02-28 (土) 0:38:35

クラス -> グレートなつくりかた

Posted by muchag | JavaScript |
初回投稿:2015-02-27 (金) 21:27:25 | 最終更新:2015-02-28 (土) 0:03:11

JavaScript は滅多に使わないので、今までクラスとは無縁できたけど、これからは是非クラスを利用していきたい。

以前、つかみ という JavaScript クラスの基本について書いたけど、今回は グレートなつくりかた という記事を見つけたので、改めて基本記事を作成。

グレートなつくりかた
  1. var hoge = (function() {
  2.  
  3.   var FOOFOO = 777; // クラス内定数
  4.  
  5.   // constructor
  6.   var hoge = function(arg) {
  7.     this.x = 5;
  8.     this.y = 10;
  9.     this.z = arg;
  10.   };
  11.  
  12.   var p = hoge.prototype;
  13.  
  14.   p.f1 = function() {
  15.     return true;
  16.   };
  17.  
  18.   p.f2 = function() {
  19.     return false;
  20.   };
  21.  
  22.   return hoge;
  23. })();
  24.  
  25. var instance = new hoge(1);
  26. // hoge {x: 5, y: 10, z: 1, f1: function, f2: function}

Qiita:【javascript】やさしいクラスの作り方
より引用。
 
この書き方だと、1クラス1ブロックになって、見やすい。 😎
 
せっかくなので、覚書用に改変。

  1. var hoge = ( function() {
  2.  
  3.   var FOOFOO = 777; // クラス内定数
  4.   var foo = 777;    // クラス内変数
  5.  
  6.   // constructor
  7.   var hoge = function( arg ) {
  8.     this.x = 5;
  9.     this.y = 10;
  10.     this.z = arg;
  11.   };
  12.  
  13.   // 内部関数(クラス内メソッド)
  14.   function moge() {}
  15.  
  16.   var p = hoge.prototype;
  17.  
  18.   p.f1 = function() {
  19.     return true;
  20.   };
  21.  
  22.   p.f2 = function() {
  23.     return false;
  24.   };
  25.  
  26.   return hoge;
  27. })();
  28.  
  29. var instance = new hoge(1);
  30. // hoge {x: 5, y: 10, z: 1, f1: function, f2: function}

 

参考サイト

Qiita:【javascript】やさしいクラスの作り方
Qiita:[JavaScript]クラス、関数、オブジェクト クラス

Posted by muchag | JavaScript |
初回投稿:2015-02-27 (金) 21:27:25 | 最終更新:2015-02-28 (土) 0:03:11

クラス -> つかみ

Posted by muchag | JavaScript |
初回投稿:2011-10-27 (木) 16:57:36 | 最終更新:2015-02-27 (金) 23:56:40

JavaScript でのクラスは、Java やらなんやらのクラスとはちょいと違うらしい。

キーワードは prototype
prototype っていわれたら、ライブラリしか思いつかなかった私は
最初意味不明だった。

で、グーグル先生に教えてもらったことをまとめてみる。

相変わらずちゃんと理解してないので間違いは多いと思われ・・・。
でも、こうやってまとめることで理解を深めるしかないのよね。

クラスベースとプロトタイプベース

まぁ、何でも最初は用語を覚えないといけないんだけど
今回もこういう定義があるらしいので、そっからスタート。

Java なんかのオブジェクト指向は「クラスベース
JavaScript は「プロトタイプベース」なんだそうな。

  • クラスベース クラスのインスタンスがオブジェクト
  • プロトタイプベース オブジェクトを元(プロトタイプ)にしたオブジェクト

 

記法
生成
  1. var Animal = function() {};

クラス名の先頭は大文字。

他人のソースを見て、この記述を初めて見たときビックリした。
変数に無名関数を代入?

でも、こういう意味だったのねぇ。
 

インスタンス化
  1. var anim = new Animal();

変数名の先頭は小文字。
 

コンストラクタ

生成時にコンストラクタによってメンバ変数とメソッドを定義できる。

  1. var Animal = function(name, sex) {
  2.  
  3.     this.name = name;
  4.     this.sex = sex;
  5.  
  6.     this.toString = function() {
  7.         window.alert(this.name + " " + this.sex);
  8.     };
  9. }
  10. var anim = new Animal("トクジロウ", "オス");
  11. anim.toString(); // 「トクジロウ オス」

 

動的に追加
  1. var Animal = function(name, sex) {
  2.     this.name = name;
  3.     this.sex = sex;
  4. }
  5. var anim = new Animal("トクジロウ", "オス");
  6. anim.toString = function() {
  7.     window.alert(this.name + " " + this.sex);
  8. };
  9. anim.toString(); // 「トクジロウ オス」

以上のように動的に追加することも可能だが
この場合は、インスタンス anim 固有のメソッドとなる。

つまり、新たにインスタンス化したオブジェクトには反映されない。
 

プロトタイプ・オブジェクト

今までのは基本だけど、上述のような記述だと
インスタンス化する度に全てメモリに領域確保をするので
以下のような記法が推奨らしい。

  1. var Animal = function(name, sex) {
  2.     this.name = name;
  3.     this.sex = sex;
  4. }
  5.  
  6. Animal.prototype.toString = function() {
  7.     window.alert(this.name + " " + this.sex);
  8. };
  9.  
  10. var anim = new Animal("トクジロウ", "オス");
  11. anim.toString(); // 「トクジロウ オス」

もちろんメンバ変数も定義可能。

プロトタイプ・オブジェクト を利用することで
そのメソッドを利用するときだけ読み込みに行くのでメモリを節約できるみたい。
 

リアルタイム認識

その他のメリットとして、インスタンス生成後にメソッドを追加しても有効らしい。

  1. var Animal = function() {};
  2. Animal.prototype.name = "サチ";
  3. var anim = new Animal();
  4.  
  5. Animal.prototype.sex = "メス"; // インスタンスの生成後にメンバを追加
  6.  
  7. window.alert(anim.sex); // 「メス」

 

保持内容は個別
  1. var Animal = function() {};
  2.  
  3. Animal.prototype.name = "サチ";
  4. var a1 = new Animal();
  5. var a2 = new Animal();
  6.  
  7. window.alert(a1.name + "|" + a2.name); // 「サチ|サチ」
  8.  
  9. a1.name = "トクジロウ";
  10. window.alert(a1.name + "|" + a2.name); // 「トクジロウ|サチ」

 
a1 は書き換えられた値。
a2 はデフォルトの値。
 

hasOwnProperty

こうなると、格納先が2箇所で区別しないといけなくなるので
hasOwnProperty というメソッドが存在する。

  1. function Constructor() {}
  2. Constructor.prototype.prop1 = 30;
  3.  
  4. var objA = new Constructor();
  5.  
  6. // objA 自体は持っていないので false。
  7. alert(objA.hasOwnProperty("prop1"));
  8.  
  9. objA.prop1 = 100;
  10.  
  11. // objA 自体が持っているので true。
  12. alert(objA.hasOwnProperty("prop1"));

 

オブジェクト・リテラル定義

プロパティ・オブジェクトを利用するに当たって

  1. Animal.prototype.name = "サチ";

という記述を繰り返すと

  • 可読性の下落
  • 変更が煩雑

という問題が起こるので

  1. var Animal = function(name, sex){
  2.     this.name = name;
  3.     this.sex = sex;
  4. }
  5.  
  6. Animal.prototype = {
  7.     getVoice : function() {
  8.     window.alert(this.name + "「チュウ!」");
  9.     },
  10.     toString : function() {
  11.         window.alert(this.name + " " + this.sex);
  12.     }
  13. };
  14.  
  15. var anim = new Animal("トクジロウ", "オス");
  16. anim.toString(); // 「トクジロウ  オス」

このように記述することができるようだ。

VB でいうところの With 文だと思えばいいや。
 

引用&参考元サイト

CodeZine:プロトタイプ(prototype)によるJavaScriptのオブジェクト指向
@IT:Ajax時代のJavaScriptプログラミング再入門 第4回 JavaScriptでオブジェクト指向プログラミング

Posted by muchag | JavaScript |
初回投稿:2011-10-27 (木) 16:57:36 | 最終更新:2015-02-27 (金) 23:56:40