<<前回「CoffeeScriptって何?」へ<<

 CoffeScriptを3時間で理解するための10のポイントのうち、ポイント1から3までを解説します。ポイント1は「CoffeeScriptはコンパイルで即時関数に変換される」こと、ポイント2は「変数は自動的に宣言される」こと、ポイント3は「リテラルで豊かな表現を可能に」したことです。

POINT1 CoffeeScriptはコンパイルで即時関数に変換される

★「即時関数」でグローバル変数を作らない
★JavaScriptのstrictモードにも対応

 CoffeeScriptで記述されたコードをコンパイルすると、JavaScriptのコードは、(function() {...}).call(this);でラップされた状態で出力されます(リスト7*1。奇異にも見える書き方ですが、実は、JavaScriptの世界では定石とも言える書き方の一つです。匿名関数を定義しておいて、その場で即座に実行することから「即時関数」と呼ぶこともあります。

リスト7●CoffeeScriptから自動生成されるJavaScriptコードの外枠
リスト7●CoffeeScriptから自動生成されるJavaScriptコードの外枠

 でも、よくわかりませんね。その場ですぐに実行するならば、なぜわざわざ関数として定義するのでしょうか。関数を「再利用したい処理をまとめたもの」と理解している人にとっては、なんとも違和感があるのではないでしょうか。

即時関数で変数を封じ込める

 即時関数の目的はすべての変数をローカル変数に封じ込めることです。JavaScriptでは、関数の外側の変数はすべてグローバル変数と見なされます。しかし、グローバル変数が多くなってくると、変数の名前が衝突する可能性が高まり、潜在的なバグの原因になります。「グローバル変数はできるだけ少なく」というのはJavaScriptに限らず、コーディングの鉄則です。

 グローバル変数を減らすにはどうしたら良いでしょうか。その答が即時関数なのです。コード全体を関数でラッピングすることで、すべての変数をローカル化しているわけです。即時関数とは、変数をローカルスコープに押し込めるための便宜的な関数であると言えます。

新しいstrictモードにも対応

 即時関数を呼び出しているcall(this)の部分にも注目です。callはFunction(関数)オブジェクトが提供するメソッドで、「関数の第1引数に与えられたオブジェクトをthisとして、関数を呼び出し」ます。言い換えれば、即時関数の中ではcallメソッドの第1引数のオブジェクトをthisキーワードで呼び出せます。この例では、callメソッドにはthis(グローバルオブジェクト)が渡されています。従って、Webブラウザー環境であればwindowオブジェクトが即時関数の中のthisに引き継がれます。

 もっとも、標準的なJavaScriptの挙動では関数の中のthisはグローバルオブジェクトになりますので、thisの引き渡しを意識する必要はありません。よって、即時関数というと、「(function() {...})();」のような構文で紹介されていることも多いはずです。しかし、この書き方には一つ問題があります。

 JavaScriptのstrictモード*2を有効にした場合、関数内のthisは、グローバルオブジェクトではなく、undefinedになってしまうのです。環境によってthisの内容が変わってしまうのは不都合なので、CoffeeScriptのコンパイラは常に明示的にthisの引き渡しをしているわけです。