音の鳴るブログ

鳴らないこともある

CoffeeScript Traps

CoffeeScriptで機嫌よく書いていたら、いつのまにか無駄っぽいコードが生成されることがある。 そういう例と解決方法です。CoffeeScript 1.4.0 で確認しました。

愚かな3項演算子

# coffee
a = new Float32Array(1024)
for i in [0...a.length]
    a[i] = Math.random()
// js
a = new Float32Array(1024);
for (i = _i = 0, _ref = a.length; 
     0 <= _ref ? _i < _ref : _i > _ref; // <-- ???
     i = 0 <= _ref ? ++_i : --_i) {     // <-- ???
  a[i] = Math.random();
}

解決方法: by 1 を付ける

# coffee
a = new Float32Array(1024)
for i in [0...a.length] by 1 # <-- !!!
    a[i] = Math.random()
// js
a = new Float32Array(1024);
for (i = _i = 0, _ref = a.length; _i < _ref; i = _i += 1) {
  a[i] = Math.random();
}

邂逅の配列

# coffee
f = (a)->
    for i in [0...a.length] by 1
        a[i] = Math.random()
// js
f = function(a) {
  var i, _i, _ref, _results;
  _results = []; // <-- ???
  for (i = _i = 0, _ref = a.length; _i < _ref; i = _i += 1) {
    _results.push(a[i] = Math.random()); // <-- ???
  }
  return _results; // <-- ???
};

解決方法: 明示的になんらかの値を返す

# coffee
f = (a)->
    for i in [0...a.length] by 1
        a[i] = Math.random()
    0 # <-- !!!
// js
f = function(a) {
  var i, _i, _ref;
  for (i = _i = 0, _ref = a.length; _i < _ref; i = _i += 1) {
    a[i] = Math.random();
  }
  return 0;
};

分割代入の亡霊

# coffee
[a, b, c] = [1, 2, 3]
// js
 _ref = [1, 2, 3], // <-- ???
a = _ref[0], b = _ref[1], c = _ref[2];

解決方法: 使わない

# coffee
a = 1
b = 2
c = 3
// js
a = 1;
b = 2;
c = 3;

事実上の定数

これは純粋にJavaScriptの話ですが一応書いておきます。 何回も this を参照せずにローカル変数を使うというやつです。

# coffee
for i in [0...1024]
    a[i] = @x++
// js
for (i = _i = 0; _i < 1024; i = ++_i) {
  a[i] = this.x++;
}

解決方法: いったんローカル変数に代入する

# coffee
x = @x
for i in [0...1024]
    a[i] = x++
@x = x
// js
x = this.x;
for (i = _i = 0; _i < 1024; i = ++_i) {
  a[i] = x++;
}
this.x = x;

特にパフォーマンスが気にならないような部分では、あまり気せずに書いたほうが良いと思います。 僕は後者2つはだいたい放置しています。