11

ChromeとFirefoxでこれを実行すると、異なる答えが得られます。

(function() {

        if(true) {
            function f() { alert("yes"); };
        } else {
            function f() { alert("no"); };
        }
        f();

    })();

Chromeでは結果は「いいえ」です。Firefoxでは結果は「はい」です。

なぜ違いがあるのですか?

4

3 に答える 3

13

条件ステートメント内で関数を宣言することは標準的ではないため、そうしないでください。これは既知の問題です。宣言の代わりに関数式を使用できます。

var f;
if(true) {
    f = function() { alert("yes"); };
} else {
    f = function() { alert("no"); };
}
f();

関数式に関する有名な Kangax の記事には、いくつかの追加の詳細が記載されています。

FunctionDeclarationsは、 ProgramまたはFunctionBodyでのみ使用できます。構文上、これらはブロック内に表示できません ({ ... })ifwhileまたはforステートメントのように。これは、ブロックにはStatementsのみを含めることができ、FunctionDeclarationであるSourceElementsを含めることができないためです。

同記事には次のようにも書かれています。

仕様に従って、実装は構文拡張(セクション 16 を参照) を導入することが許可されていますが、それでも完全に準拠していることに言及する価値があります。これはまさに、最近非常に多くのクライアントで起こっていることです。それらのいくつかは、ブロック内の関数宣言を他の関数宣言として解釈します — 単純にそれらを囲んでいるスコープの先頭に持ち上げます。その他 — 異なるセマンティクスを導入し、少し複雑なルールに従います。

于 2013-01-09T17:06:45.497 に答える
5

V8 (Chrome JavaScript エンジン)バグトラッカーから:

バグではありません。Firefox は、期待どおりの動作をする唯一のブラウザーです。

これに対する Safari および IE の動作は、Chrome の/V8 のものと同じです。

于 2013-01-09T17:08:55.537 に答える
2

これは、ECMAScript 5 で考案されたように、Firefox に関数巻き上げがないために発生します。

Chrome は、関数の本体を実行する前に f() に値を正しく割り当てるため、f() の最初のバージョンは 2 番目のバージョンによって上書きされます。

SpiderMonkey (Firefox の JavaScript エンジン) は、値を f() に事前に割り当てずにコードを実行するため、途中で遭遇する唯一の値を使用します。function f() { alert("yes"); };

関数巻き上げとは?
JavaScript の関数スコープは、関数内で宣言されたすべての変数が関数の本体全体で見えることを意味します。不思議なことに、これは変数が宣言される前にさえ見えることを意味します。JavaScript のこの機能は、非公式に巻き上げと呼ばれます。JavaScript コードは、関数内のすべての変数宣言 (関連する代入は除く) が関数の先頭に「巻き上げ」られているかのように動作します。

ソース:
http://statichtml.com/2011/spidermonkey-function-hoisting.html
2011 - オライリー - JavaScript - 決定版ガイド第 6 版

于 2014-09-01T12:03:46.627 に答える