6

ブロック スコープで関数を定義するときに問題が発生しました。次のプログラムを検討してください。

try {
    greet();

    function greet() {
        alert("Merry Christmas!");
    }
} catch (error) {
    alert(error);
}

私は、このプログラムが警告することを期待していましたMerry Christmas!。ただし、Firefox では次のようになりますReferenceError

ReferenceError: greet is not defined

Opera と Chrome では、期待どおりに挨拶を警告します。

明らかに Firefox はブロック スコープ内の関数を としてFunctionExpression扱い、Opera と Chrome はそれを として扱いFunctionDeclarationます。

私の質問は、Firefox の動作が異なるのはなぜですか? どちらの実装がより論理的ですか? 規格に準拠しているのはどれですか?

JavaScript の宣言は巻き上げられることを理解しています。そのため、同じ関数が同じスコープ内の 2 つ以上の異なるブロックで宣言されている場合、名前の競合が発生します。

ただし、次のようなことができるように、関数が宣言されるたびに関数を再宣言する方が論理的ではないでしょうか。

greet(); // Merry Christmas!

function greet() {
    alert("Merry Christmas!");
}

greet(); // Happy New Year!

function greet() {
    alert("Happy New Year!");
}

これは、上で説明したブロックのスコープの問題を解決することに加えて、非常に役立つと思います。

4

1 に答える 1

5

実際、ブロック スコープ内の関数宣言は明示的に標準化されておらず、動作は実装に依存します。実装が異なれば、応答も異なります。if ステートメント内で関数を宣言しようとすると、同じ奇妙なことが起こります。

ES5 仕様では、実装者がブロック内の関数宣言を警告またはエラーとしてマークすることを推奨しています。

于 2012-12-25T03:41:09.123 に答える