読者です 読者をやめる 読者になる 読者になる

コンパイラかく語りき

文系新卒プログラマーのメモ

JavaScript : The Good Parts (良いパーツによるベストプラクティス)を読む④

JavaScript

どうも!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つのパラメータを受け取っている。それがthisarguments。(argumenysってなんだ…???)

thisはオブジェクト指向プログラミング的には非常に重要。ただし、関数の呼び出しのパターンによって値が変わってしまうらしい。

 

4.3.1メソッド呼び出しパターン

関数がオブジェクトのプロパティとして格納されている場合、メソッドと呼ばれる。メソッドが呼び出されると、thisにはそのオブジェクトが格納される。

gist55b428ced07482fcae86

こんな感じ。thisがmyObjを指しているので、this.valueはmyObjのプロパティであるvalueを指す。

また、thisをつかって自分自身のオブジェクトコンテキストにアクセスしているメソッドは、パブリックメソッドと呼ばれる。

 

4.3.2関数呼び出しパターン

関数がオブジェクトのプロパティでない場合、関数として呼び出される。

gistd8d8bc1f623ea8aaef8b

こんな感じ。thisにはグローバルオブジェクトがセットされる。これは言語設計の上の失敗である(そうなんだ!)

たとえば、オブジェクトの中で関数呼び出しを行ったとして、そのオブジェクトをthisを使って指し示すことができない。

gist9c6ef58650f6b8b14b1a

例えば、上記のコードでdoubleプロパティの定義の中で、thisを使うとグローバルオブジェクトであるwindowが呼ばれてしまう。なので、this.valueはundefinedになり、計算を行うはずのdoubleは空振りしてしまう(エラーにならないのがJSらしい…笑)

 

4.3.3コンストラクタ呼び出しパターン

JavaScriptプロトタイプ継承を行う言語である。つまり、あるオブジェクトが他のオブジェクトから直接継承を行う。

関数をnewを使って呼び出した場合、新しいオブジェクトが作られることになり、thisにはそのオブジェクトが格納される。そしてそのオブジェクトは呼び出しを行った関数のprototypeへのリンクを持っている(複雑ぅー)

 

giste8604f2581a6aaabf6ed

ここで、Quoはnewをつけて呼び出されることを前提としており、コンストラクタと呼ばれる。先頭は大文字で始めるのが習慣。ただし、new演算子を使ってコンストラクタ関数を呼び出す方法はあまり良い方法ではない。

 

4.3.4apply呼び出しパターン

JavaScriptは関数型オブジェクト指向言語なので、関数はメソッドを持つことができる。

applyメソッドを使うことで、引数を格納した配列を使って関数を呼び出すことができる(???)さらに、applyメソッドを使うことで、thisにセットされる値を自由に設定することができる(すごい)

gist6084522de9c925cc8728

statusObjはget_statusを持っていないにも関わらず、applyを使うことでstatusを取得できる。

(うーん、いまいちちゃんと理解できていないかも…)

 

4.4引数

argumentsを使えばたくさんの引数を処理できる。

gistddf92dd0d5eb60d54fa3

 ただし、argumentsは本物の配列ではないので、length以外に配列の持つプロパティやメソッドを持っていない。

 

4.5戻り値

戻り値が指定されていない場合は、戻り値はundefinedとなる。

 

4.6例外

(えっ、ちょっと待って!JSに例外ってあったんだ!衝撃!)

こんな風に記述。

gist07be5905294a7ca663a4

tryはその後のオブジェクトをまるごと返すんですね!

 

4.7変数型の拡張

これすごい。

giste2b554ad344e5c09f7a8

それぞれのNumberやStringって、実行時には3や” neat ”に置き換わるんですね!基本型のデータについて実は理解していなかったのかも…

 

えっと、自分でも拡張してみました

f:id:chuck0523:20150808160207p:plain

拡張はできました!すごい!

 

4.8再帰

関数の中で、自分自身の関数を呼び出すこと。ただし、再帰を非常に深く行う場合はリソースを使いきって処理に失敗する可能性がある。(for文で条件文をミスって無限ループになると起こりますよねw)

 

4.9スコープ

スコープとは変数の生存期間や、アクセス可能範囲を定めるものである。

ただし、JavaScriptのブロックは残念なことにスコープを生成しない。唯一スコープを生成するのは関数であり、これは関数スコープと呼ばれる。

 

4.10クロージャ

以前作成したmyObjというオブジェクトに関して、valueというプロパティを関数を作成して保持できる。

gist5402010fa370449ffa52

valueが関数のスコープ内に置かれて、他のプログラムからアクセスできなくなった。

 

4.11コールバック

非同期処理に用いる関数。(説明が20行くらいしかなかった…(;・∀・))

(JSでの非同期の処理、まだ僕ぜんぜんできない。Ajaxとかできて当たり前な感じだし、勉強したい…!)

 

4.12モジュール

モジュールとは、インターフェースは提供するけど内部の状態や実装については隠蔽されている関数やオブジェクトのこと。らしい。モジュールパターンでは、関数スコープとクロージャを利用してデータの束縛とプライベート化を行いことができる。なおかつ、グローバル変数を使わずに済む!!!

 

4.13カスケード

こんなのもあるんだ。

メソッドが戻り値を持たない場合でも、undefinedの代わりにthisを返すようにすれば、カスケードが行える。カスケードを行うと、1つの分の中で同じオブジェクトの複数メソッドを連続して呼び出せるようになる。(ふーん)

 

4.14カリー化

難しくて省略…ヽ(´Д`;)ノアゥア…

qiita.com

 

4.15メモ化

重複した処理を防ぐためなどに、オブジェクトに操作の結果を記憶しておくことができます。

blog.h13i32maru.jp

 

 

まとめ

ハードだった…・゚・(つД`)・゚・ 

ようやくthisの違いを学び始めた人間にとって、まだまだレベルの高い内容でした…

でも、いつかカスケード、カリー化、メモ化をきっちり理解して使えるようになりたいですね!

 

では!