CoffeeScriptを使う理由

More than 5 years have passed since last update.

随時更新します。


  1. CoffeeScriptを使う理由

  2. TypeScriptを使う理由

  3. AltJSを使わない理由

  4. Dartを使う理由

仕事でCoffeeScriptを使う場合の説得材料まとめです。


なぜJavaScriptではいけないのか


クラス定義がないからです

みんな大好きオブジェクト指向をするために必須なのにJavaScriptではクラスは書けません。

いや、正確には書けます。


クラス定義

function Person() {};


なんだクラスは簡単に書けるじゃないかと思いましたか?



クラス定義その2

function Person() {

this.name = "takashi";
this.age = 20;
};
Person.prototype.echo = function () {
return "Hello " + this.name + " !!";
};

コンストラクタ、メソッドを書いただけで、コード量が増えてきましたね。

毎回クラス名とprototypeと書く必要があります。

めげてきましたか?

私はめげてます。


次は継承してみましょう。


継承

function inherits(ctor, superCtor) {

ctor.super = superCtor;
ctor.prototype = Object.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
});
};

inherits(Employee, Person);
function Employee() {
Person.apply(this, arguments);
};

Employee.prototype.echo = function () {
return "Hello " + Employee.super.prototype.echo.call(this);
};


どうでしょうか?

継承元を呼び出すのにEmployee.super.prototype.echo.call(this)のように書かないといけません。

継承の方法は今まで迷走していたので各々実装方法も違います。

詳しく知りたい場合はこちらを参照するといいです。

そんな継承はイヤだ - クラス定義 - オブジェクト作成


勘違いしてしまうfor文

以下のコードは間違っています。


間違ったfor...in

var ary = [100, 200, 300];

for (var i in ary) {
console.log(i);
}

JavaScriptでinは配列のeachではありません。

オブジェクトのプロパティ名をeachする命令です。


正しいfor...in

var obj = {key1: 100, key2: 200, key3: 300}

for (var key in obj) {
console.log(obj[key]);
}


正しい配列のfor

var ary = [100, 200, 300];

for (var i = 0 ; i < ary.length ; i++) {
console.log(ary[i]);
}


functionという記述が長過ぎる

JavaScriptはシングルスレッドなので、callbackを多用します。

多用するのに毎回functionと書かなければいけません。

後からコードを見直すとfunctionだらけで頭が痛くなることでしょう。


functionが長過ぎる

var self = this;

$.get("/users", function (users) {
var result = [];
$.each(users, function (user) {
result.push(new User(user));
});
return result;
}).done(function (users) {
self.users = users;
}).fail(function (xhr, status, msg) {
console.error(msg);
});


グローバル汚染を防ぐためにすることがある

functionで命令を閉じ込めてあげないとグローバルに定義されるので

他のライブラリとぶつかったりします。

varを書き忘れるとグローバルになるので他のライブラリと・・・


グローバル汚染をする?しない?

// グローバル汚染します

function Person() { // グローバル汚染
name = "takashi"; // グローバル汚染
this.word = "Hello " + name + " !!"; // でも動くよ
}
new Person();
name; // -> takashi

// グローバル汚染しません
(function () {
function Person() {
var name = "takashi";
this.word = "Hello " + name + " !!";
}
new Person();
})();
name; // undefined



比較が曖昧

比較時に勝手に変換すると予期せぬ挙動となります。

なので毎回===と書かなくてはいけない。


比較例

""           ==   "0"           // false

0 == "" // true
0 == "0" // true
false == "false" // false
false == "0" // true
false == undefined // false
false == null // false
null == undefined // true
" \t\r\n" == 0 // true


CoffeeScriptを使おう

これらのよくないコードを未然に防いでくれるのがCoffeeScriptです。

それぞれ例をみていきましょう。


クラス定義

class Person

constructor: () ->
@name = "takashi"
@age = 20

echo: () ->
"Hello #{@name} !!"

class Employee extends Person
constructor: () ->
super

echo: () ->
"Hello #{super()}"



for文

# 配列のループ

ary = [100, 200, 300]
for value in ary
console.log value

# プロパティのループ
obj = {key1: 100, key2: 200, key3: 300}
for key, value of obj
console.log(value)



function文

$.get "/users", (users) =>

result = [];
$.each users, (user) =>
result.push(new User(user))
return result
.done (users) =>
@users = users
.fail xhr, status, msg =>
console.error(msg)


グローバル汚染しない

# CoffeeScriptコンパイル時にbare=trueで関数で囲んでくれる

class Person
constructor: () ->
@name = "takashi" # インスタンス変数
@word = "Hello #{name} !!" # ローカル変数
}
new Person()
name # -> undefined


比較は厳密

""           ==   "0"           # false

0 == "" # false
0 == "0" # false
false == "false" # false
false == "0" # false
false == undefined # false
false == null # false
null == undefined # false
" \t\r\n" == 0 # false

どうですか?

ダメなコードも未然に防げて、かつ簡素なコードでしょう?


CoffeeScriptはコンパイルしてJavaScriptを出力するけど、デバッグはどうするの?

CoffeeScriptにはSourceMapを出力するオプションが存在します。

これは出力されたJavaScriptがCoffeeScriptのどのコードの位置とマッチするかの情報を含んだファイルです。

これをChromeに食わせることにより、CoffeeScriptでデバッグが行えます。

詳しいやり方はグーグルでCoffeeScript source map chromeとかで検索するといいです。

ですが私が今までCoffeeScriptで開発してきた経験からいうと、出力されたJavaScriptをそのままデバッグした方が楽にデバッグできます。

CoffeeScriptが何行かのJavaScriptを出力しているために、同じ行でデバッガーのNext Stepを何回する必要があるため、変なところで進んだり止まったりしてデバッグしにくいです。

consoleにそのままCoffeeScriptを貼付けて動作させることもできないので、わざわざ変換するのが面倒だったりします。

CoffeeConsole?あれは忘れた方がいい。

CoffeeScriptは別言語なのではなく、JavaScriptのシンタックスシュガーです。

CoffeeScriptとJavaScriptの命令は1対1で簡単に結びつきます。

なので出力されたJavaScriptで苦もなくデバッグすることができます。


ちょっと注意、魔法の杖ではありませんよ。

HibernateしかりActiveRecordしかり、ORMはDBの設計、SQLをある程度知っていて始めて使用することができます。

ORM使うからSQL知らなくても問題ないぜー!!バリバリー!!

みたいなことはしてませんよね?

CoffeeScriptもご多分に漏れずJavaScriptをある程度知っている必要があります。

いきなりCoffeeScriptから始めます!

というようなことは避けた方が懸命です。

JavaScriptを軽く学習させてからCoffeeScriptを学習させてください。

そうしないとデバッグで死にます。


わかりました。CoffeeScriptを使います。

ようこそCoffeeScriptの世界へ。

あたなはCoffeeScriptを採用したことで以下の恩恵を受けることができます。


  1. ソースコードが簡素になったことで保守性があがります。

  2. JavaScriptの罠に嵌らなくなります。

あれ?少ない?

いえいえ、すごく大事な2点です。

塵積です。


でも待って・・・実は問題山積みなんです。

CoffeeScriptはコンパイルが必要です。

このコンパイルを甘く見てはいけません。

やってみればわかります。めんどいです。

私もCoffeeScriptコンパイルジプシーです。

・・・この投稿はとりあえずここまで!!

次回私が行ったCoffeeScriptのコンパイル方法の変遷を紹介します。

書きました。

私のCoffeeScriptをコンパイルする方法の変遷