javascript goodparts 第4章まとめ


プログラミング　＝　一連の要求仕様を関数とデータ構造に分解するための作業

４．１　Functionオブジェクト
jsにおいて　関数はオブジェクト
オブジェクト　＝　複数の名前と値のペア

FunctionオブジェクトはFunction.prototypeにリンクされている　

全ての関数は生成される際にさらにもう２つの隠されたプロパティを持つ
・関数の振る舞いを決めるためのコンテキスト
・コード


関数はオブジェクトなのでそれ以外の値と同様に扱える
関数を変数やオブジェクト、配列に格納できる
関数を他の関数の引数として渡せる
戻り値として関数を渡せる

他のオブジェクトと異なる点
・それを呼び出せる


4.2　関数リテラル
var add = function(a, b) {
     return a + b;
};


4.3 関数の呼び出し

関数を呼び出すとき、引数以外に２つのパラメータを自動的に受け取る
this
arguments

this 呼び出しのパターンによって異なる
・メソッド呼び出し
・関数呼び出し
・コンストラクタ呼び出し
・apply呼び出し

thisという追加パラメータがどのように初期化されるかという点にある


関数の引数について
・引数の数とパラメータが一致していなくてもエラー発生なし
・引数足りなかったら残りのパラメータにはundefined
・引数の値に対して型チェックなし
・どのパラメータにどの値を渡してもいい

4.3.1　メソッド呼び出し
関数がオブジェクトのプロパティとして格納されるときメソッドと呼ばれる


メソッドではthisを使ってオブジェクトにアクセスできる
this.へのオブジェクトのセットのタイミングは　呼び出しが発生したタイミング　＝　遅延束縛


4.3.2　関数呼び出し
オブジェクトのプロパティでない関数　関数として呼び出し
この場合のthis グローバルオブジェクト

thisについて調べる

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

js プロトタイプ継承を行う　＝　オブジェクトが他のオブジェクトから直接継承する

関数呼び出し時 new演算子を前に着けていた場合新しいオブジェクト生成
thisには新しいオブジェクトがセットされる

オブジェクト　新しい関数のprototypeプロパティへの隠されたリンクを持つ


コンストラクタ　大文字で始まる変数に格納するのが慣例
newを使わずに呼び出した場合　よくない場合があるのに警告が出ない

そもそもnewでコンストラクタ呼び出すのはおすすめでない


4.3.4 apply呼び出しパターン
関数はメソッドを持てる

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

applyメソッドの２つの引数
・thisにセットしたい値
・パラメータの配列

// ２つの数値の配列を作り、それらを足し合わせる
var array = [3,4];
var sum = add.apply(null, array);

// statusというメンバを持つオブジェクトを生成
var statusObject = {
     status: 'A-OK'
};

// statusObjectオブジェクトはQuo.prototypeを継承していない
// しかしstatusObjectがget_statusメソッドを持っていないにもかかわらず
// statusObjectのメソッドを呼び出すことが可能になる
var status = Quo.prototype.get_status.apply(statusObject);


4.4　引数
argumentsという配列　呼び出された関数内で利用できる追加パラメータ
指定したパラメータよりも多く渡されてもすべての引数にアクセスできる

var sum = function() {
     var i, sum = 0;
     for (i = 0; i< arguments.length; i+=1) {
          sum += arguments[i];
     }
     return sum;
};


4.5　戻り値
return 戻り値指定されてないときは undefined



4.7 変数型の拡張
jsで　標準で用意されている変数型を拡張できる
Function.prototypeを拡張するｋ十で、すべての関数で利用できるメソッドを追加できる

Function.prototype.method = function(name, func) {
     this.prototype[name] = func;
     return this;
};

標準で用意されている変数型を拡張することで表現力を飛躍的に高められる


4.8 再帰



4.9 スコープ
ブロックスコープをもっていない
関数スコープは持っている
→　関数内のどこで定義された変数でも、関数内のどこからでもアクセス可能

ブロックスコープをもたないjavascriptでは、関数内で使用するすべての変数を関数の一番先頭で定義する



4.12モジュール

オブジェクト内に実態参照の名前とそれが指し示す文字の一覧を保持する必要がある場合、どこに保持するか
・グローバル変数
　影響が大きいので無理
・関数内で定義
　呼び出されるたびにリテラルが評価されるのでコストが大きい

・クローじゃの中に格納し、実態参照を追加するためのメソッドをもう１つ追加する
理想

String.method('deentityify', function() {

     //実態参照テーブル
     var entity = {
          quot: '"',
          lt: '<',
          gt: '>'
     };

     //deentityifyメソッドを返す
     return function() {

          return this.replace(/&([^&;]+);/g;
               
                function (a, b) {
                    var r = entity[b];
                    return typeof r === 'string' ? r : a;
               }
          );
     };
}());

モジュールパターンでは、関数スコープとクローじゃを活用してデータの束縛とプライベート化を行える
deentityfyメソッドだけが実態参照テーブルにアクセスできる


4.13　カスケード
メソッドが返り値を持たない場合　return;　で書くのがふつう
↑undefinedが返ってくる

undefinedのかわりにthisを返すようにすればカスケードができるようになる

return this


カスケードをすると
１つの文の中で同じオブジェクトの複数のメソッドを連続して呼び出せるようになる
jQueryとかによくある
getElement('myBoxDiv').move(300,500).//////

カスケードを使うことで
複数の処理を１度にまとめて行うインターフェースを作ってしまう危険性を防止できる
処理毎にメソッド分割
http://blog.livedoor.jp/ishiduca/archives/51010921.html


4.14カリー化
jsにおいて　関数は値である

カリー化とは
関数に引数を固定して新しい関数を作成する

var add1 = add.curry(1);
document.writeln(add1(6));


curryメソッドは標準では用意されていない
Function.prototypeを拡張すると追加できる

Function.method('curry', function() {
     var args = arguments, that = this;;
     return function() {
          return that.apply(null, args.concat arguments));
     };
)};
↑なにかが間違ってる


curryメソッド
元の関数と、カリー化する引数を保持したクローじゃを生成する。
戻り値となる関数では、カリー化された引数と実際に渡された引数をまとめて元の関数を呼び出す処理が行われる

↑のコード argumentsは本物の配列でない　concatメソッドはそのままでは使えない
→配列のsliceメソッドを両方のargumentsメソッドに適用　
こうすることで本物の配列がさくせいされ、concatメソッドが動くようになる

Function.method('curry', function() {
     var slice = Array.prototype.slice,
         args = slice.apply(arguments),
         that = this;
     return function() {
          return that.apply(null, args.concat(slice.apply(arguments));
     };
});


カリー化のメリット
カリー化された関数に引数を渡すだけで、別の機能を持つ関数を簡単に作り出せる

4.15 メモ化
関数は不要な処理を省略するために、前回の操作の結果をオブジェクトに記憶できる