書籍転載:JavaScriptライブラリ実践活用[厳選111]
短くかつ安全で高性能なコードを書く[CoffeeScript]
書籍転載の13本目(書籍内の番号は「62」)。短い記述で、安全かつ高性能なJavaScriptコードを生成できる「CoffeeScript」の基本的な使い方を説明する。
書籍転載について
ご注意
本記事は、書籍の内容を改変することなく、そのまま転載したものです。このため用字用語の統一ルールなどはBuild Insiderのそれとは一致しません。あらかじめご了承ください。
JavaScriptは、初心者でも始めやすい言語ですが、深く理解しバグの少ないコードを書くには言語仕様上の「罠」が潜んでいます。そこで、CoffeeScriptに沿ってコードを記述することによって、その「罠」を回避し、安全で高性能なJavaScriptを生成、実行することが可能になります。
- 名称: CoffeeScript
- 分類: 小ネタ
- URL: http://coffeescript.org
- 関連ファイル: coffee-script.js、coffee-scriptモジュール
JavaScriptはブラウザで動作し、HTMLとの親和性もよく、HTMLを少々編集するような簡単なコードであれば初心者でも簡単に書くことができます。ただ、処理が複雑になっていくと、他の言語にはない特徴を持つJavaScriptの言語仕様を理解したうえでコーディングをしないと、思わぬバグが生まれたり、長く煩雑なコードになりがちです。
CoffScriptは、そのような「罠」を回避する仕組みを用意しています。JavaScriptの言語仕様を深く考えなくても、安全で高性能なコードを記述することが可能です。コードもシンプルになり、JavaScriptと比較して2分の1から3分の1の量で記述することができます。
コンパイルして実行する
CoffeeScriptで記述したコードは、JavaScriptにコンパイルして実行する必要があります。そのため、CoffeeScriptで記述したコードは、JavaScriptが動作する環境であれば、ブラウザでもNode.jsでも動作させることができます。
コンパイルは、Node.jsを使用してCoffeeScriptのインストールを行うか(図062-01)、ブラウザでCoffeeScriptのモジュールを読み込み、動的にJavaScriptにコンパイルして実行する(リスト062-01)、2つの方法があります。
coffee -c helloworld.coffee |
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>動的コンパイルサンプル</title>
<script src="js/coffee-script.js" type="text/javascript"></script>
<script type="text/coffeescript">
hello = ->
alert "Hello World!"
hello()
</script>
</head>
<body>
</body>
</html>
|
コンパイルコマンドの主なオプションは、表062-01のとおりです。
オプション | 概要 |
---|---|
-c, --compile | CoffeeScriptをJavaScriptにコンパイル |
-i, --interactive | インタプリタを起動 |
-o, --output [DIR] | JavaScript出力ディレクトリを指定する --compile や --watch と合わせて指定する |
-j, --join | コンパイル前に、すべてのスクリプトを順番とおりに結合する |
-w, --watch | ソースが更新されたらすぐに再コンパイルを行う |
-p, --print | ファイル出力ではなく、標準出力にコンパイル結果を表示する |
-l, --lint | jslコマンド(JavaScriptのLint)を使ってJavaScriptのコードをチェックする |
-s, --stdio | 標準入力からcoffeeスクリプトを読んで、標準出力にJavaScriptを渡す。 例:cat src/cake.coffee | coffee -sc |
-e, --eval | オプションに書かれたコードを実行する |
-r, --requiure | コンパイルまたは実行する前に、ライブラリを読み込む |
-b, --bare | コンパイル結果が即時関数に囲まれず、各変数がグローバルとして宣言される |
-v, --version | バージョンを表示 |
-h, --help | ヘルプを表示 |
リスト062-01のサンプルのように、CoffeeScriptのコードは、scriptタグのtype属性をtext/coffeescriptとすることで、CoffeeScriptと認識されて動的コンパイルされます。動的コンパイルは毎回コンパイル処理が動作することになり、パフォーマンスが悪化するためデバッグでの利用で留めておき、本番環境ではコンパイル済みのJavaScriptを使うようにしましょう。
また、コマンドを使って対話形式でCoffeeScriptの実行結果が確認できる簡易インタプリタが用意されています(図062-02)。coffeeコマンドを実行し、関数や構文をコマンドすると、実行結果やリターンの値を表示されます。コーディングする際に、インタプリタを使って実行結果を確認してもよいでしょう。
CoffeeScriptの基本的な記述方法
まず、CoffeeScriptの基本的な記述方法を見ていきます。リスト062-02の構文には、5つのポイントがあります。
###
複数行にわたるコメント
###
# 単行のコメント
# セミコロンは不要
x = 1
# 演算子(==ではなくis)の違い
if x is 1
# ブロック(JavaScriptでいう「{...}」)はインデントで表現
# 1関数の実行はカッコがあってもなくてもよい
alert("Hello World!")
alert "Hello World!"
|
このポイントを押さえたうえで、リスト062-03のコンパイル後の構文と比較してみてください。
/*
複数行に渡るコメント
*/
(function() {
var x;
x = 1;
if (x === 1) {
alert("Hello World!");
alert("Hello World!");
}
}).call(this);
|
・コメントの記述方法
複数行に渡るコメントは「###~###」、単行のコメントは「#」で記述します。ただ、コンパイル後、単行の「#」のコメントは削除されます。
・セミコロンは不要
末尾のセミコロンは不要です。JavaScriptでも改行ごとのセミコロンは必ずしも必須ではありませんが、それは文の継続が前提であり、セミコロンが全く不要というわけではありません。その曖昧な点がバグの温床になります。
・演算子の違い
if文などで使う演算子が異なります。通常、JavaScriptは厳密に型を評価するには、「==」ではなく「===」を使用する必要がありますが、無意識に型を厳密に評価しない「==」を使用することがバグの温床になります。
・ブロックはインデントで表現
ブロックを「{...}」ではなくインデントで表現します。JavaScriptもたとえばif文は「{...}」ブロックを使用しなくても1つの構文だけであれば記述できますが、無意識に複数の構文を書いてしまいバグの温床になることがあります。
・関数の実行はカッコがあってもなくてもよい
1のように、関数の実行時はカッコがあってもなくても動作します。
コンパイル後に生成されるJavaScript
コンパイルを行うと、図062-03のようにJavaScriptが生成されます。これだけのコードでも意識せずに生成された構文があると思いますが、ここにJavaScriptの言語としての特性が示されています。これは、CoffeeScriptがJavaScriptの特性を活かしたうえで、バグの危険を回避しやすいよう補っているのです。変換されるポイントとして、演算子、即時関数、変数宣言がありますが、その3点をこの後説明します。
変換されるポイント演算子
JavaScriptは、たとえばif文の等しいという意味の演算子を「==」や「===」で記述することができます。この2つの記述方法は、意味合いが異なります。「==」は、文字列や数値の場合には数値を文字列に変換して評価をします。「===」は変換して評価をしません。そのため、「==」は曖昧な評価となりバグの温床となります。
そこで、CoffeeScriptは表062-02のような演算子が用意されています。それぞれ、型の曖昧さは排除して評価をすることができるうえ、比較演算子としても文章のようにわかりやすくなっています。
CoffeeScript | JavaScript | 使用例 |
---|---|---|
is | === | a is 100 |
isnt | !== | b isnt 200 |
not | ! | not flag |
and | && | a is 100 and b isnt 200 |
or | || | a is 100 or b isnt 200 |
yes,on | true | flag is yes |
no,off | false | flag is off |
@ | this | @age |
変換されるポイント即時関数に変換される
CoffeeScriptで記述されたコードをコンパイルすると、JavaScriptのコードは、必ず(function() {...}).call(this);の中に記述されます(リスト062-03)。これは、即時関数と言われており、関数ではありますが、中の処理はその場で実行されます。
これはJavaScriptでの定石とも言える書き方です。なぜこのような書き方をするかというと、変数宣言をこの中に閉じ込めるためです。リスト062-03の例を見ると、変数は「var x」として宣言されていますが、この宣言のスコープは即時関数の中のみで、その外では使用できません。もし、即時関数の中に記述しない場合は、他の場所でも使用できてしまうため、グローバル変数となり、全く別の処理に影響する可能性も否定できません。そのため、即時関数が自動生成しています。
変換されるポイント自動で変数宣言
CoffeeScriptは、変数のvar宣言が必須ではありません。これは、宣言しないという意味ではなく、CoffeeScriptが自動的に変数を宣言するからです。というのも、JavaScriptは変数のスコープが関数内と関数外で曖昧なものになっているため、同じ変数名を付けるなどによりバグの温床になります。
そこで、CoffeeScriptでは、「現在のスコープの先頭」に必ずvar宣言するように出力されます。つまり、変数の宣言位置と変数の有効範囲を一致させることで、曖昧な挙動を回避しています。
※以下では、本稿の前後を合わせて5回分(第11回~第15回)のみ表示しています。
連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。
11. RSpec風の構文でBDD用のテスト・コードを記述する[Jasmine]
書籍転載の11本目(書籍内の番号は「108」)。RSpec風のテスト・コードが書けるBDD(ビヘイビア駆動開発)テスティング・フレームワーク「Jasmine」の基本的な使い方を説明する。
12. JasmineのSpy機能でテストダブルを作成する
書籍転載の12本目(書籍内の番号は「109」)。Jasmineでテスト対象オブジェクトが持つメソッドの戻り値を固定値に変更したり、そのメソッドが実行されたかどうかを検証したりするために、Spy機能を使用する方法を解説。
13. 【現在、表示中】≫ 短くかつ安全で高性能なコードを書く[CoffeeScript]
書籍転載の13本目(書籍内の番号は「62」)。短い記述で、安全かつ高性能なJavaScriptコードを生成できる「CoffeeScript」の基本的な使い方を説明する。
14. オブジェクト指向でコードを記述する[CoffeeScript]
書籍転載の14本目(書籍内の番号は「63」)。CoffeeScriptを使用すると、クラスベースのオブジェクト指向で記述できる。その内容を説明する。
15. 処理を短く記述する[CoffeeScript]
書籍転載の15本目(書籍内の番号は「64」)。CoffeeScriptの基本構文のうち、数値や文字列表現、配列、for~in、unless/untilの記述方法を説明する。