#267 CoffeeScript Basics
- Download:
- source codeProject Files in Zip (84 KB)
- mp4Full Size H.264 Video (21 MB)
- m4vSmaller H.264 Video (12.2 MB)
- webmFull Size VP8 Video (14.2 MB)
- ogvFull Size Theora Video (33.9 MB)
CoffeeScriptは、コンパイルしてJavaScriptを生成する言語です。Rails 3.1に含まれたので、もうすぐ多くのRails開発者が初めて目にすることになるでしょう。今回のエピソードでは、既存のJavaScriptコードをCoffeeScriptに変換していきます。これがこの言語を知る有効な方法です。変換するJavaScriptは、エピソード261 [動画を見る, 読む]で書いたクレジットカード番号を検証するコードです。
今までにCoffeeScriptを使ったことがない場合は、CoffeeScriptのウェブサイトから始めるのがいいでしょう。そこで、いくつかのCoffeeScriptコードの例とそれぞれをコンパイルしたJavaScriptを見ることができます。それに加え、サイトにはCoffeeScriptコードを入力してその場でコンパイルされたJavaScriptを確認できるページもあります。コンパイルされたJavaScriptはブラウザで実行することができ、これらはサーバへのAJAX呼び出しを行うことなくすべてクライアント側で実行されます。
これから変換するJavaScriptコードは、下のページで使われているものでユーザがクレジットカード番号フィールドからタブキーで抜けるときに起動されます。これは、入力された番号に対してmod 10を用いて基本的な検証を行い、番号が不正だった場合にテキストフィールドの横にメラーメッセージを表示します。
これを行うJavaScriptは以下のとおりです。
var CreditCard = { cleanNumber: function(number) { return number.replace(/[- ]/g, ""); }, validNumber: function(number) { var total = 0; number = this.cleanNumber(number); for (var i=number.length-1; i >= 0; i--) { var n = +number[i]; if ((i+number.length) % 2 == 0) { n = n*2 > 9 ?n*2 - 9 : n*2; } total += n; }; return total % 10 == 0; } }; $(function() { $("#order_credit_card_number").blur(function() { if (CreditCard.validNumber(this.value)) { $("#credit_card_number_error").text(""); } else { $("#credit_card_number_error").text("Invalid credit card number."); } }); });
なお、このアプリケーションで使用しているRailsのバージョンは、この記事の執筆時の最新版である3.1 RC1です。gem install rails --pre
を実行することでアップグレードが可能です。
最初の変更
JavaScriptファイルをCoffeeScriptファイルに変えるには、ファイル名に.coffee
を追加します。Rails 3.1のアプリケーションでも、拡張子を.js
のままにしておけば引き続きJavaScriptファイルを使用することができます。CoffeeScriptの使用は完全に任意です。
まずJavaScriptファイルのコードをコメントアウトして、一つずつそれに対応するCoffeeScriptに置き換えていきます。最初に変換する部分は、スペースやハイフンを除いて入力された番号を整形するcleanNumber
関数にします。
var CreditCard = { cleanNumber: function(number) { return number.replace(/[- ]/g, ""); } }
対応するCoffeeScriptのコードは以下のようになります。
CreditCard = cleanNumber: (number) -> number.replace /[- ]/g, ""
CoffeeScriptでは、多くのJavaScriptの構文を取り除くことができます。CoffeeScriptはタブでブロックレベルを定義するので、すべての波カッコを削除できます。これはつまりスペースの使い方に一貫性が必要になるということです。
さらにvar
キーワードが不要になるためすべて削除します。関数の最後の部分のreturn
キーワードも不要です。これはちょうどRubyと同じように、関数の最後の値が自動的に返されるからです。セミコロンもCoffeeScriptでは不要なため削除できます。
引数を渡す関数呼び出しでは、引数をカッコで囲む必要がなくなるのでこれも削除します。例外は引数を持たない関数を呼び出すときです。この場合は関数が呼び出されたことをCoffeeScriptに知らせるためにカッコが必要です。
最後に関数の呼び出し方を変更します。function
キーワードを削除して、代わりに関数の引数の後に->
を付けます。慣れるまでに少し時間がかかるかも知れませんが、これはCoffeeScriptで関数を定義する簡便な方法です。
この部分を変更したら、コンパイルしてどのようなJavaScriptを生成するかを見てみます。出力されたものは、元のコードに非常に似ています。
var CreditCard; CreditCard = { cleanNumber: function(number) { return number.replace(/[- ]/g, ""); } };
次にこのJavaScriptコードの中では、大きな方であるvalidNumber
関数を見てみましょう。
validNumber: function(number) { var total = 0; number = this.cleanNumber(number); for (var i=number.length-1; i >= 0; i--) { var n = +number[i]; if ((i+number.length) % 2 == 0) { n = n*2 > 9 ?n*2 - 9 : n*2; } total += n; }; return total % 10 == 0; }
同じような手順でこのコードを書き換えていくと、次のCoffeeScriptができ上がります。
validNumber: (number) -> total = 0 number = @cleanNumber(number) for i in [(number.length-1)..0] n = +number[i] if (i+number.length) % 2 == 0 n = if n*2 > 9 then n*2 - 9 else n*2 total += n total % 10 == 0
前と同じように波カッコとセミコロンを取り除きました。var
とreturn
キーワードをとり、function
を->
に置き換えました。コードをきれいにするためにさらにその他の変更を加えました。
thisへの参照があったら@
記号に置き換えることができるので、this.cleanNumber
は@cleanNumber
になります。if
文の外側のカッコも不要なので取り除きます。三項演算子も変わったので、C言語タイプの疑問符とコロンをif then else
構文に置き換えて、if
を最初に置いて、疑問符をthen
に変更し、コロンをelse
に変更します。
コードの他の部分は良さそうです。後はfor
ループを変えるだけです。CoffeeScriptによる繰り返し処理はJavaScriptと異なるため、コードを変更する前に確認しておきましょう。配列に対する繰り返しはこのようなコードになります。
for number in [1,2,3] alert number
これが以下のJavaScriptを生成します。
var number, _i, _len, _ref; _ref = [1, 2, 3]; for (_i = 0, _len = _ref.length; _i < _len; _i++) { number = _ref[_i]; alert(number); }
またはもう一つの方法として、以下のように書いても同じJavaScriptを生成します。
alert number for number in [1,2,3]
連続した数字の場合は、配列の代わりに範囲を使うことができます。
for number in [1..3] alert number
これによって、生成されるJavaScriptをより単純化できます。
var number; for (number = 1; number <= 3; number++) { alert(number); }
ループのカウントを増やすのではなく減らしたい場合は、範囲で指定する数字を逆にします。
for number in [3..1] alert number
これはfor
ループの振る舞いと似ているので、同じようなカウントダウンと置き換えられます。
JavaScriptコードの最後の残りの部分に進みます。
$(function() { $("#order_credit_card_number").blur(function() { if (CreditCard.validNumber(this.value)) { $("#credit_card_number_error").text(""); } else { $("#credit_card_number_error").text("Invalid credit ↵ card number."); } }); });
このjQueryのコードは、クレジットカード番号フィールドのblur
イベントに検証用コードを付加します。CoffeeScriptでjQueryコードを扱う場合にも特別な処理は不要です。対応するCoffeeScriptのコードは以下のようになります。
jQuery -> $("#order_credit_card_number").blur -> if CreditCard.validNumber(@value) $("#credit_card_number_error").text("") else $("#credit_card_number_error").text("Invalid credit ↵ card number.")
前と同じように波カッコとセミコロンを取り除き、function
を->
に、this
への参照を @
にそれぞれ置き換えます。もう一つ行った変更は、最初の$
の呼び出しをjQuery
に変えたことです。これは機能には影響はないのですが、これによりjQueryを使用していることが明確になります。
JavaScriptコードをすべてCoffeeScriptに変更できたので、ブラウザでページを再読み込みし正しく表示されるか見てみましょう。
うまくいきました。無効なクレジットカード番号を入力するとエラーメッセージが表示され、有効な番号を入力するとメッセージが消えます。生成されたJavaScriptファイルの最後の部分には、CoffeeScriptファイルからコンパイルされたJavaScriptを見ることができます。
(function() { var CreditCard; CreditCard = { cleanNumber: function(number) { return number.replace(/[- ]/g, ""); }, validNumber: function(number) { var i, n, total, _ref; total = 0; number = this.cleanNumber(number); for (i = _ref = number.length - 1; _ref <= 0 ?i <= 0 : ↵ i >= 0; _ref <= 0 ?i++ : i--) { n = +number[i]; if ((i + number.length) % 2 === 0) { n = n * 2 > 9 ?n * 2 - 9 : n * 2; } total += n; } return total % 10 === 0; } }; jQuery(function() { return $("#order_credit_card_number").blur(function() { if (CreditCard.validNumber(this.value)) { return $("#credit_card_number_error").text(""); } else { return $("#credit_card_number_error").text("Invalid ↵ credit card number."); } }); }); }).call(this);
デバッグ
CoffeeScriptのコードに文法エラーがあった場合はどうなるでしょうか? CoffeeScriptファイルをわざと間違えて記述して、そのページをブラウザで見ても、JavaScriptリクエストは別なのでエラーは表示されません。しかし開発者用コンソールを見てみると、エラーがリスト表示されています。
エラーメッセージを見れば、何行目のコードの何が問題かについて十分な情報があるので、コードのどこをデバッグすればいいかがわかります。
今回のエピソードは以上です。CoffeeScriptについてここで触れられなかった点もたくさんあるので、CoffeeScriptのサイトでこの楽しい小さな言語についてさらに学んでみてはいかがですか?