2011-01-30 4 views
1

誰かがJavaScriptの謎を解きほぐしてくれますか?JavaScript - 関数を呼び出さずに関数内に変数を保存する

は、次のJavaScriptコードを考えてみましょう:

var a[]; 

for (i=0;i<10;i++) 
{ 
    a[i] = function(){alert ("I am " + i);}; 
} 

a[5](); 

今、明らかに、最後の行は、アラートがiの値であるため、「私は午前5時」「私は午前9時」、そしてない読まようになります9ループはforループの最後にあります。

アラートに、「想定されているもの」を出力したいが、配列から関数を呼び出す方法を変更しないで、つまりパラメータはない。

ヒント:別の関数を呼び出す関数を定義してみてください。

助けてください! :-)

答えて

6

あなたが受け取ったヒントは少し欺瞞的です。あなたは別のものを呼び出す関数を定義したくない(同じ問題があるだろう)。むしろ、を返すものを定義したいとします。

例:http://jsfiddle.net/sX92Q/

var a = []; 

for (i = 0; i < 10; i++) { 
    a[i] = alertFunc(i); 
} 

    // return a function that closes around the proper value of "i" 
function alertFunc(i){ 
    return function() { 
     alert(i); 
    }; 
}; 

a[5](); 

これは効果的にループに匿名関数を使用するものと同じであるが、匿名関数は、各反復を再構成する必要がないので、より効率的です。

一般に、ループ内に重複機能を作成したくない場合。


サイドノート。 JavaScriptでは、この:

var a[]; 

は次のようになります。

var a = []; 
+1

エレガントで良いコメントも下に説明! +1 –

4

ありがとうこれは動作します:あなたの例では

var a = []; 

for (i=0;i<10;i++) 
{ 
    a[i] = (function(i) { 
     return function(){alert ("I am " + i);}; 
    })(i); 
} 

a[5](); 

を、無名関数は、しかし、この変数は関数の作成後に変更され、i変数への参照を保持しています。したがって、関数を呼び出すときに、その変更された値が表示されます。

これを避けるには、その変数のコピーを作成する必要があります。これは、上記のコードのとおりです。

for (i=0;i<10;i++) 
{ 
    let j = i; 
    a[i] = function(){alert ("I am " + j);}; 
} 
+0

はどうもありがとうございました! –

1

次のコードは動作します:

var a[]; 

for (i=0;i<10;i++) 
{ 
    a[i] = (function(i) { 
     return function(){alert ("I am " + i);}; 
    })(i); 
} 

a[5](); 
ここ

iがローカル変数に変換され

また、Javascriptを1.7にあなたはlet定義を使用します。

+1

-1 @levuあなたは関数を返す必要があります。ここで定義されていない[i]を定義しました。 – Raynos

+0

@raynos:u r right :) – levu

1
var a[]; 

for (i=0;i<10;i++) 
{ 
    a[i] = function(){alert ("I am " + i);}; 
} 

a[i = 5](); 

チート以来(I = 5)

=== 5はactaully上記の真の解決策のこの

いずれかを使用しないでください。また

:あなたの最初の例は動作しません

var a = []; 

for (i=0;i<10;i++) 
{ 
    (function(j) { 
     a[j] = function() { 
      alert ("I am " + j); 
     }; 
    }(i)) 
} 

a[i](); 

i

+0

非常に悪い解決策... – levu

+0

@levuしかし、それはボックスソリューションの外で楽しいと思います!面接の質問であれば、私はむしろそれに代わり答えてくれるはずです。 – Raynos

+0

私はこれが彼の問題の解決策ではないと言います;)これは解決策です。それは遺伝子型対表現型のようなものです。これは表現型の解決法です。 – levu

0

j現在の値を作るためにクロージャを使用した理由は、データがどこかを保存する必要があり、です。あなたは10個の異なる値を格納していますが、iという変数が1つしかないので、動作しません。

他のポスターは、動作するクロージャを使用することを提案していますが、あなたの質問は呼び出し関数なしで行う方法を探しています。

これはもちろん、同じことをするときに10種類の機能があるのはなぜですか?なぜだけでなく:

var whoAmI = function(i){ alert("I am " + i); }; 
whoAmI(5); 

おそらく、あなたは引数なしでそれを呼び出すいくつかの外部APIに周りに渡すことができる機能が必要ですか?その場合、クロージャー機能はそれを機能とするものです。

+0

私は投票できません申し訳ありません+2;) –

+2

これは本当に質問に答えません。同じインデックスを持つものを参照するために、その値を覚えておく関数でループ内の 'i'の現在の値を閉じる必要があるときがあります。私はこれが概念を説明するための単純な例に過ぎないと確信しています。 – user113716

+0

確かにいくつかの可能性がありますが、呼び出す10の関数のうちどれを呼び出すかを知るためには、その情報を簡単に渡すことができます。次に、パラメータのない関数(jQueryの成功コールバックなど) 。私はこのポスターが何を望んでいるのか分かりません。 – jpsimons

関連する問題