1

重複の可能性:
ループ内の Javascript クロージャー - 簡単な実用例

私はこれに似たものをコーディングしようとしていました:

var funcs = [];
for (var i=0; i<5 ; ++i) {
    funcs[i]=function() {
        alert(i);
    };
}

明らかに、変数が無名関数によってキャプチャされ、いずれかを呼び出すと、'4' (最後の反復の後の値であり、作成されたすべての関数によって共有される)がアラートされるため、呼び出しは期待どおりにfuncs[0]アラートしません。0ifuncs[0..4]i

私の頭に浮かぶ最初の回避策は、ある種の関数ジェネレーターを使用することです:

var funcs = [];
for (var i=0; i<5 ; ++i) {
    funcs[i]=(function(cap) {
        return function() {alert(cap)};
    })(i);
}

これでうまくいきますが、本当に不可解で読みにくいようです。関数ラッパーを使用せずに意図した動作を取得するより良い方法はありますか?

4

5 に答える 5

2

この.bind関数を使用すると、バインドされた関数に追加のパラメーターを事前にバインドできます。

var funcs = [];
for (var i=0; i<5 ; ++i) {
    funcs[i]=function(i) {
        alert(i);
    }.bind(this, i);
}

これはES5機能であるため、IE9 +、Chrome、Safari、Firefoxで動作するはずです。

于 2012-09-07T14:29:49.627 に答える
2

できるだけ簡単に書く必要があります。わかりやすいと思いますが、読みにくいです。したがって、これを単純化する1つの方法は、ネストされたコーディングスタイルを使用することです。今ほど簡単なことはないと思います。

私はこの方法を提案します:

var funcs = [];

for (var i = 0; i < 5; ++i) {
    funcs[i] = (
        function (cap) {
            return function () { alert(cap) };
        }
    )(i);
}
于 2012-09-07T14:30:24.137 に答える
1

IMHO、名前付き関数は、パフォーマンスと読みやすさの両方の理由から、多くの場合優れています。このようにしてみませんか:

function foo (cap) {
    return function () { alert(cap) };
}

var funcs = [];
for (var i=0; i<5 ; ++i) {
    funcs[i]=foo(i);
}
于 2012-09-07T14:31:11.800 に答える
0

これを試して:

var funcs = [0, 1, 2, 3, 4].map(function(i) {
    return function() {alert(i);};
});

注: mapIE8 以前ではサポートされていませんが、共通のポリフィルがあります。

于 2012-09-07T14:32:16.590 に答える
0

コードにこれらの無名関数を埋め込みたくない場合の解決策は、状態 (i) と関数 (プロトタイプ内) の両方を埋め込む (名前付きの) クラスを定義することです。それはよりLOCですが、時にはより読みやすいです:

var funcs = [];
function MyFunc(i) {
   this.i=i;
}
MyFunc.prototype.doIt = function(){
   alert(this.i);
};
for (var i=0; i<5 ; ++i) {
    funcs[i]=new MyFunc(i);
}

funcs[2].doIt();​
于 2012-09-07T14:26:43.490 に答える