8

関数の配列があり、それぞれを順番に呼び出す簡潔な方法を探しています。

fns = [
    function a() { console.log('a') },
    function b() { console.log('b') },
    function c() { console.log('c') },
]

これは機能します:

fns.map(function (f) { f() })

そしてこれもそうです:

fns.map(function (f) { Function.call.call(f) })

ただし、これは TypeError を発生させます。

fns.map(Function.call.call)

後者の例が機能しないのはなぜですか?

4

3 に答える 3

5
for (var i = 0, len = fns.length; i < len; i++) {
    fns[i].call();
};

ここに作業フィドルがあります。

関数を呼び出すには、上記のようにFunction.prototype.callandを使用します。とをFunction.prototype.apply使用すると、実行スコープと関数呼び出しを渡すことができます。それが必要ない場合は、次のようにするだけです。callapplyarguments

for (var i = 0, len = fns.length; i < len; i++) {
        fns[i]();
};

コードについて:

Array.prototype.mapcallbackとを取る関数ですscope as parameters。最初の 2 つの例では、無名関数を として使用しており、callbackによって自動的に渡されたパラメーターを呼び出しますArray.prototype.map。展開すると、コードは次のようになります。

function single(element) {
   element();
};
fns.map(single);

したがって、上記は完全に正しいです。を使用して同じ原則に従って、マップによってパラメーターとして渡されたFunction.call.call関数を呼び出しています。f

しかし、あなたの3番目の例では、直接call経由を強制していますがFunction.call.prototype.call、この場合、fパラメータとして渡されなくなりました。つまり、Function.call.callを呼び出そうとundefinedするため、TypeError. Function.call.callの中map()に入れると、 aを引数として渡しません。callback

callすぐになります。は, orFunction.call.callとまったく同じもので、3 番目の例で行ったように使用するとすぐに評価されます。Function.call.call()Function.call.call(undefined)

于 2013-04-10T10:23:30.573 に答える
4

この単純化されたコードには、同様の問題があります。

var x = Function.call.call;
x(alert);

この場合、一度Function.call.call呼び出されると、元のコンテキスト (つまり ) は記憶されませんFunction.call。このコンテキストを保存するには、この不浄な構成のトリックを使用できます。

Function.call.bind(Function.call)

Function.callのコンテキストがそれ自体にバインドされる新しい関数を返し、コンテキストを保存します。この式を新しい変数に保存できます。

var callFn = Function.call.bind(Function.call);

callFn(alert)と同じですalert.call()。追加の引数はそのまま渡されることに注意してcallFn(alert, window)くださいalert.call(window)。この動作を理解することはcallFn、 get が などのコールバックの一部として呼び出される状況で重要Array.forEachです。これにより、各反復で 3 つの引数が渡されます。

fns.forEach(callFn);

あなたの場合、内部の関数fnsは渡された引数を使用していませんが、舞台裏では次のように呼び出されます。

fns[0].call(0, fns)

したがってthis、要素のインデックス (つまりNumber(0)) にarguments[0]等しく、関数の配列に等しくなります。鋭敏な観察者は、要素の値が亀裂の間にあることに気付いたかもしれませんが、それでもarguments[0][this]orを使用して参照されている可能性がありますarguments.callee(非推奨)。

于 2013-04-10T10:48:26.287 に答える