音の鳴るブログ

鳴らないこともある

JavaScript の var の位置

JavaScript のコードスタイルに var をどのように書くかというのがある。JavaScript の仕様では関数以外にスコープをつくる方法はなくて、しかも関数内で宣言された変数はいかなる場所で宣言されていたとしても、全部関数の先頭部分で宣言しているのと同じことになるし、ブロックはスコープに対してなんの意味ももたない。と言うことで、だいたい先頭部分にまとめましょうとか一つの var しか許さないことにしましょうとか言うのだけど、僕は最近使う場所で宣言するようにしている。例なので変なプログラムを書くけど、こんな感じ。

// リストの各要素からリストの平均値で引き算する
function deviations(list) {
  // ----- 合計を求める -----
  var sum = 0;
  for (var i = 0; i < list.length; i++) {
    sum += list[i];
  }

  // ----- 平均を求める -----
  var avg;
  if (i !== 0) {
    avg = sum / i;
  }

  // ----- 平均で引き算する -----
  var result = [];
  for (var i = 0; i < list.length; i++) {
    result[i] = list[i] - avg;
  }
  return result;
}

こういう気持ち悪いコードを書いている。気持ち悪いポイントは以下。

  • var i が 2回ある (jshint, eslint で怒られる)
  • avg の計算に i を使っている (eslint だと block-scoped-var で警告)
  • そもそも var が途中に出てくるとキモイ (美意識の問題)

このプログラムですべての変数を冒頭の var で宣言してしまうと、機械には怒られなくて、時間差で人間に怒られることになる(僕は他の人と作業していないので想像だけど)

何でこんなに気持ち悪いことになっているのかというと、コメントに書いてある通りで 合計の計算 → 平均の計算 → 引き算 と複数の処理が行われているからで、そのたびに var が出現していてそこから気持ち悪さが滲み出している。キモさの可視化ともいえる。

こういう気持ち悪いコードを書いてしまうと魂がダメになっていくし、後で人間に怒られるのは嫌なので早々に修正したくなる。そのときに var の位置がコードを分割する目安になるし、どうにもこうにも変な位置に var が残るのであればオブジェクトとして分割するとか設計に問題があるとか検討しやすくなる。もし最初に var の位置を先頭に持ってきたばかりに機械に怒られず後で人間に怒られて修正するはめになったときでも有効で、とりあえず var を使う位置に移動させると先の理由で修正しやすくなる。

ということで、var を使う場所に書いて気持ち悪いコードを書いている。

function sum(list) {
  return list.reduce(function(a, b) {
    return a + b;
  }, 0);
}

function average(list) {
  if (list.length === 0) {
    return 0;
  }
  return sum(list) / list.length;
}

function deviations(list) {
  var avg = average(list);
  
  return list.map(function(x) {
    return x - avg;
  });
}