function hoge(){} と var hoge=function(){} の違い

javascriptはあまり得意ではなくて、この件について、定期的に忘れて同じ質問を人にしてしまっているので、ここに書いておく。
function hoge(){} と var hoge=function(){} に違いはあるのか? という問題について。結論から書くと、hogeのスコープが違う。(2010/10/08追記:誤りです。スコープは一緒ですね。うまく言えませんすみません…)

まず、無名functionをvarに入れた場合。

hoge(); // => エラー! hogeはundefined値
var hoge = function() {
  alert("hello!");
}

hoge()を呼び出している部分は、var hogeの宣言より上に書いてあるのでエラーになる。
一方で、名前つきfunctionを定義した場合はというと、

hoge(); // => "hello!"
function hoge() {
  alert("hello!");
}

なんと、hogeの宣言より上でもhoge()を呼び出すことができた。と、まあこういう違いがあるのでした。

おまけ

この件と関連して、興味深い挙動がある。

alert(foo); // => エラー! fooは存在しない

宣言されていない変数fooを表示しようとすると、当然、エラーになる。重要なのは、このfooは、いわゆる JSの undefined値が入っているのではなく、変数自体が存在しない状態であるということ。

一方で、次のように、alertの下にfooを宣言する行を追加してみる。

alert(foo); // => "undefined"
var foo = "bar";

この場合、"undefined" というalertが表示される。

まとめ

  • function 宣言は、そのfunctionがあるスコープに入ったときに先読みされて、functionより上の行であっても呼び出し可能になる。
  • var 宣言は、そのvarがあるスコープに入ったときに先読みされて、undefinedで初期化される。

なんか間違ってたら教えてください。