じゃあ結局Javascriptの関数定義ってどっちで書けばいいんだ?

Javascriptの本を読んでいると、関数の定義にはfunction式と文があり、それぞれ性質の違いがあるようなことが書かれている。

//こうやって書いたり
function tmp() {
    //何か処理
}

//こうしてみたり
var tmp = function () {
    //何か処理
};

前者後者の違いは主に、前者では巻き上げが行われ、後者は行われないというもの。

(function () {
    //tmpはこの地点で未宣言なのになぜか呼び出せてしまう。
    tmp();
    
    function tmp() {
      window.alert("unko!");
    }
}());

つまり前者の方がルーズなコードになりがち、ということだ。本に書かれているのは大体ここまで。わざわざルーズなコードを書く必要はないワケで、それじゃあいつも後者 var ... のスタイルを使えばいいのか? ってのは当然の疑問だ。
私の経験則に従えば、基本的にはその方針、つまりいつでも var... を使うという方針で問題ない。その実 var ... の方針で書けないソースというのは非常に珍しく、どうしても書けないのは(関数間で相互参照があるなど)、そのソース自体に何か問題がある。 Javascript を勉強したこともない人間(大抵はJavaプログラマーだ)が「なんとなく」書いてみて、「オレ Javascript 知らねえから」と言い訳を垂れ流しているようなものだ。それは言語の問題ではない。つまりクソだ。
それでも実のところ前者を使うべきケース無いということではない。以下の二つがそれに該当する。

  1. グローバル関数を作成する場合
  2. 変数代入前に宣言が確立されているべきケース。

まっとうなソースを書いているのであれあば、グローバル関数の作成は共通関数の作成など極一部に限られるはずだ*1。もちろん共通関数とて var ... で書けない事は無い。が、わざわざ var で宣言したオブジェクトに「代入」する必要もない。
他方、変数代入前に宣言が確立されているべきケースとは、具体的に再起で発生する。以下の例は Javascript としては適当に動作するが、厳密には怪しい部分が隠されている。

var tmp = function (str) {
    str += " unko!";
    if (str.length < 20) {
        //この function が宣言されたタイミングでは tmp はまだ undefined
        tmp(str);
    } else {
        window.alert(str);
        return;
    }
};

var ... の記法はあくまで無名関数の変数への代入だ。この無名関数は宣言時に undefined である tmpの呼び出しを行っていることになり、厳密にはエラーとなる。もっとも実際に tmp が実行される際には既に代入はすんでいるため、動作はするだろうが、ソース内にエラーがあると判りながら放置するのは気持ちが悪いものだ。再起関数の宣言と共に実行&後から再度呼び出すようなトリッキーなケースではダイレクトにエラーすら発生する。おめでとう、言い訳無しだ!

var tmp = (function (str) {
    str = str || "";
    str += " unko!";
    if (str.length < 20) {
        //ここでコケる
        return tmp(str);
    } else {
        window.alert(str);
        return tmp;
    }
}());

従って以下のようにする。

function tmp(str) {
    str += " unko!";
    if (str.length < 20) {
        tmp(str);
    } else {
        window.alert(str);
        return;
    }
}

もしくはこうする。

var tmp = function tmp(str) {
    str += " unko!";
    if (str.length < 20) {
        tmp(str);
    } else {
        window.alert(str);
        return;
    }
};

この2ケース以外では常に var... を使っていればいい、というのが結論となるが…、皆様のご意見を伺いたい。

*1:グローバル関数をひとつでも作成するのが「まっとう」なのかという議論はひとまず置いておく