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

Engineer as a Lifestyle @tenkoma

tenkoma's testing blog

カリー化,スコープチェーン,Callオブジェクト…

JavaScript 第5版 p.140
カリー化とは、ある関数の引数をあらかじめ指定した、新しい関数を定義すること。
スコープチェーンってなんだっけ?p.57ページで説明があったのに忘れている。スコープチェーンとは、それぞれのスコープ(グローバルスコープ、関数内スコープ)で、変数を探すためもの。そこには、スコープチェーンにはスコープで参照可能なオブジェクトが並んでいて、順番に探していくことで、「変数名の解決」ができる。
Callオブジェクトとかでてきた。関数の引数やarguments、関数内でvar定義した変数は全部Callオブジェクトとやらのプロパティになるらしい。

function init(){
    // do something
}
init();

こうすると、グローバル名前空間を最小限の汚染で済むようにできる。でももっと謙虚にやるには無名関数を定義してそのまま呼び出せばいい。

(function(){
    //do something
})();

何度か見たことがあるけど、理解できないうちは気持ち悪いだけの構文である。理解できると、便利そうな気がしてきた。
p.143
関数の実行が終了しているのにスコープは残っていて参照可能ってのは気持ち悪いなー、おもしろいけど。
現時点での簡単な理解だと関数の中に関数が入れ子になっているとする。(便宜上、外側の関数と入れ子の関数と呼ぶ)、入れ子の関数を変数として戻り値にすると、外側の関数は処理が終了しているのに、そのスコープには入れ子の関数からアクセスが出来る状態が生まれる。
サンプルとしては不適当かもしれないが下のようなコードを考えてみた。

function hoge(){
    var x = {y:1};
    return {
        set: function(a){
            x.y = a;
        },
        get: function(){
            return x.y;
        }
    };
}
obj = hoge();
obj.get(); // >> 1
obj.set(5);
obj.get(); // >> 5

戻り値は、hoge関数のスコープにアクセスするメソッドをもったオブジェクトとした。
これを応用すると、複数の関数からアクセスできるが、グローバルスコープの変数でない変数、という概念ができる。クロージャ - Wikipediaの説明に依ればレキシカル変数と呼ぶらしい。
こんな複雑な例を思いつかなくても、p.144に書いてある。