Panda Noir

JavaScript の限界を究めるブログでした。最近はいろんな分野を幅広めに書いてます。

CoffeeScriptで変数を初期化せず宣言のみ行いたかった

(この記事はQiitaで僕が書いたものを移行した記事です。記事中のコメントはQiitaの該当記事を参照ください)

公式サイト(http://coffeescript.org) でみたのであってるはず。ただし動作がおかしい 追記読んでください

a = b = c = "unknown"
f = ->
  [a, b, c] = [1, 2, 3]
console.log a, b, c
f()
console.log a, b, c

これで初期化せずに宣言のみ実現出来る予定でした。それっぽい挙動しているコードがこれくらいしか公式でなかったので多分これが最善案です。ちなみにコンパイル後はこちら

(function() {
  var a, b, c, f;
  a = b = c = "unknown";
  f = function() {
    var ref;
    return ref = [1, 2, 3], a = ref[0], b = ref[1], c = ref[2], ref;
  };
  console.log(a, b, c);
  f();
  console.log(a, b, c);
}).call(this);

普通に"unknown"が代入されています…

もう少しだけ検証してみた

このコード、本当に対象スコープで宣言のみ行うように動作するのか検証してみました。

[a, b, c] = [4, 5, 6]
console.log a, b, c
do ->
  a = b = c = "unknown"
  f = ->
    [a, b, c] = [1, 2, 3]
  console.log a, b, c
  f()
  console.log a, b, c
console.log a, b, c

出力は

4 5 6
unknown unknown unknown
1 2 3
1 2 3

というものでした。コンパイルするとわかりますが"unknown"代入したところで宣言せず、はじめの[4,5,6]と代入しているところのみで宣言していました。つまり、期待しているところで宣言できませんでした。もちろんはじめの[4,5,6]という代入をなくせば意図した動作となります。なやましいですね。

コメントをいただいたので追記

どうやらCoffeeScriptの作者さんは宣言と初期化を分けることに違和感を抱いてるらしいです。バグ生んだりするから初期化のみにしようということらしいです。javascriptのあのスコープの仕組みだと宣言ないときつい箇所があると思うので考え直して欲しいですね。特にkarmaでテスト書くときに思います。