1

この奇妙な振る舞いのために、私のサイトにバグを見つけました。2番目の関数は、「1つ」ではなく「未定義」を警告します。

function test() {
    var myParam = "one"
    if (false) {
        var myParam = "two";
    }
    alert(myParam);
}
test(); // alert "one"


function testAjax() {
    var myParam = "one";
    $.ajax({
        url:    "http://url-to-get-error",
        error:  function(){
            if (false) {
                var myParam = "two";
            }
            alert(myParam);
        }
    });
}
testAjax(); // alert "undefined"

そして、以下のブロックにコメントすると、「1つ」を正しく警告します。誰かが理由を知っていますか?

if (false) {
var myParam = "two";
}

http://jsfiddle.net/EaW8D/2/を参照してください。


アップデート

みんな、私は問題を解決する方法を知っています、どうもありがとう!

しかし、問題は、jsが決して実行されないブロックに未定義を設定している理由です(if (false))。

4

4 に答える 4

5

誰かが理由を知っていますか?

myParamエラーハンドラー内で再宣言し、外部スコープで同じ名前の変数をシャドウイングします。変数宣言は関数の先頭に「持ち上げられ」ているため、コードは実質的に次のようになります。

error:  function(){
    var myParam;  // <- declaration
    if (false) {
        myParam = "two"; // <-  initialization
    }
    alert(myParam);
}

また、ifブロックは実行されmyParamないundefinedため、(初期化されていない変数のデフォルト値)になります。

これは、この動作を証明する簡単な例です。変数が持ち上げられていない場合、はfooグローバル変数(非厳密モードを想定)およびのプロパティになりますがwindow、そうではありません。

(function() {
    if(false) {
        var foo = 'bar';
    }
    foo = 'baz';
    console.log(window.foo); // yields `undefined`
}());

この問題を解決するには、を削除するだけですvar。これmyParamは、外部スコープで宣言された変数を参照しますtestAjax

error:  function(){
    if (false) {
        myParam = "two";
    }
    alert(myParam);
}
于 2012-07-18T18:39:42.937 に答える
2

もう一度作成myParamしているのでnew var

function testAjax() {
    var myParam = "one";
    $.ajax({
        url:    "http://url-to-get-error",
        error:  function(){
            if (false) {
                myParam = "two";
            }
            alert(myParam);
        }
    }); 
}
testAjax(); // alert "undefined"​

http://jsfiddle.net/mKdhx/

于 2012-07-18T18:29:06.407 に答える
2

フォームのすべての変数宣言は、関数スコープの一番上にvar myParam持ち上げられます。アクセスできないブロック内または関数の最後にある場合でも、どこかvarに宣言がある関数は、その変数名のすべてのインスタンスをローカルとして扱います。

このハンドラーについて考えてみましょう。

    error:  function(){
        alert(myParam);
        var myParam;
    }

また、下部にあるのは「この宣言の前後の両方にあるすべてのインスタンスをこの関数のローカル変数として扱う」ことを意味するundefinedため、アラートが発生します。この場合に適用されるのと同じ巻き上げが、アクセスできないロジックに適用されます。ブロックケース。var myParammyParam

于 2012-07-18T18:42:44.903 に答える
-1

2番目の状況では、myParam=oneとmyParam=twoは異なるブロックにあります。さらに、ajaxエラーのコールバックは、変数の可視性の観点からtestAjaxの「下」ではありません。これは非同期です。グローバルスコープでmyParamが必要になります

于 2012-07-18T18:30:42.523 に答える