JavaScriptは1995年にBrendan Eichによって開発された言語で、当初はブラウザ上で動的なコンテンツを実現するために設計されました。Javaとの関連性を示すために「JavaScript」という名前が付けられましたが、実際にはまったく異なる言語です。JavaScriptはJavaやC++のような構文を持つ一方で、動的型付けやプロトタイプベースの継承など、SmalltalkやSchemeに近い特徴も持ち合わせています。
このように独特な設計により、JavaScriptは長らく誤解されてきました。しかし2005年のAJAX技術の登場をきっかけに、JavaScriptはより「本格的な」プログラミング言語として認識されるようになりました。2006年にはjQueryが登場し、DOM操作やイベント処理を簡潔に記述できるようになり、多くの開発者の支持を得ました。さらに2009年にはNode.jsが登場し、サーバーサイドでもJavaScriptを利用できるようになりました。
こうした流れの中で2010年に登場したCoffeeScriptは、JavaScriptの問題点を改善し、より簡潔で読みやすいコードを書けるようにするための言語です。CoffeeScriptはRubyやPythonなどの影響を受けながら、JavaScriptの強力な機能を活かしつつ、冗長な構文を削減しています。CoffeeScriptのコードはJavaScriptにコンパイルされますが、生成されるコードは人間にも読めるほど明確です。
CoffeeScriptの基本構文
CoffeeScriptの最大の特徴の一つは、セミコロンや波括弧を省略できることです。代わりにインデントを使ってブロック構造を表現します。これはPythonに似たアプローチですが、JavaScriptの冗長さを大幅に削減できます。
| CoffeeScript | JavaScript |
|---|
|
fibonacci = (n) ->
return 0 if n == 0
return 1 if n == 1
(fibonacci n-1) + (fibonacci n-2)
alert fibonacci 10
|
var fibonacci;
fibonacci = function(n) {
if (n === 0) {
return 0;
}
if (n === 1) {
return 1;
}
return (fibonacci(n - 1)) + (fibonacci(n - 2));
};
alert(fibonacci(10));
|
CoffeeScriptでは関数定義も非常にシンプルになります。functionキーワードの代わりに->を使用し、return文も省略可能です。最後の式が自動的に返されます。
| CoffeeScript | JavaScript |
|---|
|
-> alert 'hello world'
square = (n) -> n * n
|
var square;
(function() {
return alert('hello world');
});
square = function(n) {
return n * n;
};
|
関数の引数にはデフォルト値を設定することもできます。また、スプレッド演算子(...)を使って可変長引数を扱うことも可能です。
calculateAverage = (values...) ->
sum = values.reduce (a, b) -> a + b
sum / values.length
scores = [85, 92, 78, 96]
average = calculateAverage scores...
オブジェクト指向プログラミング
CoffeeScriptはクラスベースのオブジェクト指向プログラミングをサポートしており、JavaScriptのプロトタイプベースの継承よりも直感的に記述できます。
class Vehicle
constructor: (@brand) ->
start: ->
console.log "#{@brand} started"
class Car extends Vehicle
constructor: (brand, @model) ->
super brand
honk: ->
console.log "#{@brand} #{@model} is honking"
myCar = new Car "Toyota", "Camry"
myCar.start()
myCar.honk()
このコードはJavaScriptにコンパイルされると、適切なプロトタイプチェーンが構築されます。@記号はthisのショートカットであり、インスタンス変数の定義と同時に初期化できます。
リスト内包表記
CoffeeScriptのリスト内包表記はPythonから影響を受けており、配列の操作を非常に簡潔に記述できます。
numbers = [1..10]
squares = (n * n for n in numbers when n % 2 is 0)
console.log squares # [4, 16, 36, 64, 100]
この構文はフィルタリングやマッピングを一度に行えるため、従来のforループよりも可読性が高く、エラーも少なくなります。
文字列操作と比較演算子
CoffeeScriptは文字列補間をサポートしており、Ruby風の#{}構文で変数を埋め込めます。
name = "Alice"
age = 30
message = "Hello, #{name}! You are #{age} years old."
また、等価演算子についても改善が施されています。CoffeeScriptの==はJavaScriptの===にコンパイルされるため、型変換による予期せぬ動作を防げます。
# CoffeeScript
result = "" == 0 # falseにコンパイル
# JavaScript(同等のコード)
var result = "" === 0; // false
jQueryとの連携
CoffeeScriptとjQueryの組み合わせは非常に効果的です。jQueryのメソッドチェーンをCoffeeScriptの簡潔な構文で記述することで、DOM操作がより読みやすく、保守しやすくなります。
$ ->
$('#add-task').on 'click', ->
taskText = $('#task-input').val().trim()
return unless taskText
taskElement = $("<li>#{taskText}<button class='delete'>×</button></li>")
$('#task-list').append taskElement
$('#task-input').val ''
$(document).on 'click', '.delete', ->
$(@).parent().remove()
このコードではjQueryのイベントハンドラをCoffeeScriptの構文で記述し、DOM要素の操作を簡潔に行っています。@はイベントの発生元要素を指すthisのエイリアスです。
Node.jsでの利用
Node.js環境でもCoffeeScriptは優れたパフォーマンスを発揮します。サーバーサイドでの非同期処理やファイル操作を、CoffeeScriptの簡潔な構文で記述できます。
fs = require 'fs'
path = require 'path'
processFiles = (directory) ->
fs.readdir directory, (err, files) ->
return console.error err if err
for file in files
filePath = path.join directory, file
fs.stat filePath, (err, stats) ->
return console.error err if err
if stats.isFile()
console.log "File: #{filePath}"
else if stats.isDirectory()
console.log "Directory: #{filePath}"
processFiles './documents'
このように、CoffeeScriptはクライアントサイドからサーバーサイドまで広範囲で利用可能な言語であり、JavaScriptの複雑さを解消しながらその強力な機能を活かすことができます。