どうも!chuckです。
暑いですがJavaScript:GoodPartsを元気よく読んでいきますw
第4章 関数
JavaScriptで最も素晴らしいのは関数の実装方法であるとのこと。関数とは一連の命令文を内包したJavaScriptの部品であり、コードの再利用・情報の隠蔽・プログラムの構造化のために使われる。
4.1Functionオブジェクト
JavaScriptにおける関数はオブジェクトである。オブジェクトは複数の名前と値のペアで構成されている。FunctionオブジェクトはFunction.prototypeへのリンクを持っており、それはさらにObject.prototypeへのリンクを持っている。
すべての関数は生成された時点でさらにもう2つのプロパティを持つ。それは関数の振舞を決めるためのコンテキストとコードである。
(やばい、いきなり知らない知識ばっかりだw)
4.2関数リテラル
Functionオブジェクトは関数リテラルを使って作成することができる。
var log = function(x) {
console.log(x);
};
こんな感じ。
ちなみに、関数リテラルを使った場合、外部へのコンテキストリンクも持つ、つまり、その側の変数を参照することができる。(当たり前のようだけど、考えてみたらなるほど!と思った。)
4.3関数呼び出し
すべての関数は渡された引数以外に2つのパラメータを受け取っている。それがthisとarguments。(argumenysってなんだ…???)
thisはオブジェクト指向プログラミング的には非常に重要。ただし、関数の呼び出しのパターンによって値が変わってしまうらしい。
4.3.1メソッド呼び出しパターン
関数がオブジェクトのプロパティとして格納されている場合、メソッドと呼ばれる。メソッドが呼び出されると、thisにはそのオブジェクトが格納される。
こんな感じ。thisがmyObjを指しているので、this.valueはmyObjのプロパティであるvalueを指す。
また、thisをつかって自分自身のオブジェクトコンテキストにアクセスしているメソッドは、パブリックメソッドと呼ばれる。
4.3.2関数呼び出しパターン
関数がオブジェクトのプロパティでない場合、関数として呼び出される。
こんな感じ。thisにはグローバルオブジェクトがセットされる。これは言語設計の上の失敗である(そうなんだ!)
たとえば、オブジェクトの中で関数呼び出しを行ったとして、そのオブジェクトをthisを使って指し示すことができない。
例えば、上記のコードでdoubleプロパティの定義の中で、thisを使うとグローバルオブジェクトであるwindowが呼ばれてしまう。なので、this.valueはundefinedになり、計算を行うはずのdoubleは空振りしてしまう(エラーにならないのがJSらしい…笑)
4.3.3コンストラクタ呼び出しパターン
JavaScriptはプロトタイプ継承を行う言語である。つまり、あるオブジェクトが他のオブジェクトから直接継承を行う。
関数をnewを使って呼び出した場合、新しいオブジェクトが作られることになり、thisにはそのオブジェクトが格納される。そしてそのオブジェクトは呼び出しを行った関数のprototypeへのリンクを持っている(複雑ぅー)
ここで、Quoはnewをつけて呼び出されることを前提としており、コンストラクタと呼ばれる。先頭は大文字で始めるのが習慣。ただし、new演算子を使ってコンストラクタ関数を呼び出す方法はあまり良い方法ではない。
4.3.4apply呼び出しパターン
JavaScriptは関数型オブジェクト指向言語なので、関数はメソッドを持つことができる。
applyメソッドを使うことで、引数を格納した配列を使って関数を呼び出すことができる(???)さらに、applyメソッドを使うことで、thisにセットされる値を自由に設定することができる(すごい)
statusObjはget_statusを持っていないにも関わらず、applyを使うことでstatusを取得できる。
(うーん、いまいちちゃんと理解できていないかも…)
4.4引数
argumentsを使えばたくさんの引数を処理できる。
ただし、argumentsは本物の配列ではないので、length以外に配列の持つプロパティやメソッドを持っていない。
4.5戻り値
戻り値が指定されていない場合は、戻り値はundefinedとなる。
4.6例外
(えっ、ちょっと待って!JSに例外ってあったんだ!衝撃!)
こんな風に記述。
tryはその後のオブジェクトをまるごと返すんですね!
4.7変数型の拡張
これすごい。
それぞれのNumberやStringって、実行時には3や” neat ”に置き換わるんですね!基本型のデータについて実は理解していなかったのかも…
えっと、自分でも拡張してみました
拡張はできました!すごい!
4.8再帰
関数の中で、自分自身の関数を呼び出すこと。ただし、再帰を非常に深く行う場合はリソースを使いきって処理に失敗する可能性がある。(for文で条件文をミスって無限ループになると起こりますよねw)
4.9スコープ
スコープとは変数の生存期間や、アクセス可能範囲を定めるものである。
ただし、JavaScriptのブロックは残念なことにスコープを生成しない。唯一スコープを生成するのは関数であり、これは関数スコープと呼ばれる。
4.10クロージャ
以前作成したmyObjというオブジェクトに関して、valueというプロパティを関数を作成して保持できる。
valueが関数のスコープ内に置かれて、他のプログラムからアクセスできなくなった。
4.11コールバック
非同期処理に用いる関数。(説明が20行くらいしかなかった…(;・∀・))
(JSでの非同期の処理、まだ僕ぜんぜんできない。Ajaxとかできて当たり前な感じだし、勉強したい…!)
4.12モジュール
モジュールとは、インターフェースは提供するけど内部の状態や実装については隠蔽されている関数やオブジェクトのこと。らしい。モジュールパターンでは、関数スコープとクロージャを利用してデータの束縛とプライベート化を行いことができる。なおかつ、グローバル変数を使わずに済む!!!
4.13カスケード
こんなのもあるんだ。
メソッドが戻り値を持たない場合でも、undefinedの代わりにthisを返すようにすれば、カスケードが行える。カスケードを行うと、1つの分の中で同じオブジェクトの複数のメソッドを連続して呼び出せるようになる。(ふーん)
4.14カリー化
難しくて省略…ヽ(´Д`;)ノアゥア…
4.15メモ化
重複した処理を防ぐためなどに、オブジェクトに操作の結果を記憶しておくことができます。
まとめ
ハードだった…・゚・(つД`)・゚・
ようやくthisの違いを学び始めた人間にとって、まだまだレベルの高い内容でした…
でも、いつかカスケード、カリー化、メモ化をきっちり理解して使えるようになりたいですね!
では!