カテゴリー
JavaScript

関数型プログラミング

JavaScriptは、関数型プログラミング言語ではない。
しかし、JavaScriptは関数をオブジェクトとして操作できるので、
関数型プログラミング言語のテクニックが使える。

参考書籍:

オライリー JavaScript 第6版

カテゴリー
JavaScript

クロージャ

JavaScriptは構文スコープを使う。
関数を実行するときは、関数が定義されたときに有効であった変数スコープを使う。
関数が呼び出されたときに有効な変数スコープではない。
構文スコープを実装するために、JavaScript関数オブジェクトの内部には、
関数のコードだけでなく、現在のスコープチェーンへの参照も含まれる。

入れ子型関数を呼び出して、戻り値を返す

var scope = "global scope";
function checkscope() {
    var scope = "local scope";
    function f() { return scope; }
    return f();
}
checkscope()    //local scorpe

入れ子型関数のオブジェクト自体を返す

var scope = "global scope";
 function checkscope() {
     var scope = "local scope";
     function f() { return scope; }
     return f;
 }
 checkscope()()    //何が返されるか? -> local scorpe

上のコードと下のコードの違いは、括弧がcheckscope()の中から外に移動。
構文スコープの基本となる規則
JavaScriptの関数は、定義されたときに有効なスコープチェーンを使って実行されるという規則。
つまり、下のコードは、入れ子型関数f()は、
変数scopeの値が"local scope"にバインドされているスコープチェーンのもとで定義されている。
この変数バインドは、f()を実行するときも有効で、どこで呼び出されても変わらない。
したがって、下のコードが返すのは"local scope"となる。
これがクロージャの強力な点。
クロージャは、クロージャ自身が定義された外側の関数のローカル変数(引数)バインドを抱え込む。

var uniqueInteger = (function () {
                         var counter = 0;
                         return function() { return counter++; };
}());

一見すると、コードの最初の行では、関数を変数uniqueIntegerに代入しているように見えるが、
このコードでは、関数を定義して呼び出している。
最初の行の(がポイント。
したがって、関数の戻り値が、uniqueIntegerに代入される。
戻り値は別の関数。
uniqueIntegerに代入されるのは、入れ子型の関数オブジェクト。
入れ子型の関数は、スコープ中の変数にアクセスできる。
つまり、外側の関数で定義されたcounter変数にもアクセスできる。

sample
// JavaScript
window.onload = function(){

    var f = (function(){
        var xhr = [], i;
        for(i = 0; i < 3; i++){ //for loop
            (function(i){
                xhr[i] = new XMLHttpRequest();
                url = "closure.php?data=" + i;
                xhr[i].open("GET", url, true);
                xhr[i].onreadystatechange = function(){
                    if (xhr[i].readyState === 4 && xhr[i].status === 200){
                        console.log('Response from request ' + i + ' [ ' + xhr[i].responseText + ']'); 
                    }
                };
                xhr[i].send();
            })(i);
        }
    })();
};

// PHP [closure.php]
echo "Hello Kitty -> " . $_GET["data"];

参考書籍:

オライリー JavaScript 第6版

カテゴリー
JavaScript

名前空間としての関数

変数は、その変数が定義された関数と、その関数に入れ子にされている関数中からアクセスできる。
関数中で宣言された変数はすべて関数全体からアクセスできる。
関数の外側からはアクセスできない。
関数の外側で宣言された変数はグローバル変数になり、プログラム全体からアクセスできる。

JavaScriptでは、あるコードブロック中でのみアクセス可能な変数を宣言する方法がない。
このため、一時的な名前空間として関数を定義することで、
グローバルな名前空間での変数名やプロパティ名の衝突しないようにする。

function mymodule() {
  // モジュールをここに記述する。
  // モジュールで使用する変数はすべて、この関数ローカルになり、
  // グローバルな名前空間の変数名と衝突しない。
}
mymodule(); //ただし関数を必ず呼び出すようにすること!

上記のコードだとグローバル変数に定義されるのは、「mymodule」関数のみ。
以下のように1つの式の中で匿名関数を呼び出す方法もある。

(function() {   // mymodule関数を匿名関数として書き直す
  // モジュールをここに記述する。
}());   // 関数リテラルを定義し、すぐに呼び出す。

functionキーワードの前の開き括弧に注目。
もしも開き括弧がなければ、JavaScriptインタプリタはfunctionキーワードを、
関数宣言文として解釈する。
括弧を記述することで、インタプリタは、この式を正しく関数定義式と認識する。
定義後すぐに呼び出す関数を括弧で囲むのも、慣用句となっており、
必要がないときでも括弧で囲まれることが多くなる。

参考書籍:

オライリー JavaScript 第6版

カテゴリー
JavaScript

値としての関数

JavaScriptの関数は値としても使える。
変数に代入したり、
オブジェクトのプロパティや配列の要素に格納したり、
他の関数に渡したり

参考書籍:

オライリー JavaScript 第6版

カテゴリー
JavaScript

calleeプロパティとcallerプロパティ

Argumentsオブジェクトには、
calleeプロパティ 現在実行中の関数を参照する。
callerプロパティ この関数を呼び出した関数を参照する。
も定義されている

参考書籍:

オライリー JavaScript 第6版

カテゴリー
JavaScript

可変長の引数リスト(Argumentsオブジェクト)

仮引数よりも多い数の引数で関数が呼び出された場合、
名前が付いていない値を直接参照する方法がない。
この問題を解決してくれるのが、Argumentsオブジェクト。

任意の個数の引数を受け取ることが可能な関数を、
可変長引数関数、varargs関数と呼ぶ。

参考書籍:

オライリー JavaScript 第6版

カテゴリー
JavaScript

省略可能な引数

宣言した仮引数よりも少ない数の引数でその関数を呼び出した場合、
値が省略された仮引数には、undefined値が設定される。

参考書籍:

オライリー JavaScript 第6版

カテゴリー
JavaScript

関数の引数と仮引数

JavaScriptでは、関数の仮引数に対して型を指定しない。

関数呼び出しのときにも、実際に渡される引数に対して型チェックをしない。
引数の数すらチェックしない。

参考書籍:

オライリー JavaScript 第6版

カテゴリー
JavaScript

間接的な呼び出し

call()
apply()

カテゴリー
JavaScript

コンストラクタ呼び出し

関数呼び出しやメソッド呼び出しの前にnewキーワードを記述すると、
コンストラクタ呼び出しになる。

returnを使わないのが一般的