17

のようなJavascript配列メソッドには、コールバックを呼び出すためのコンテキストとして使用されるパラメーターがありますforEachthisArg

array.forEach(callback[, thisArg])

、、、および。every_ some_ ただし、そのようなパラメータはありません。これには特別な理由がありますか、それとも必要ない理由がありますか?filtermapreducereduceRight

たとえば、次を使用した機能合成の次の実装について考えてみますreduceRight

function compose () {
    var fns = [].slice.call(arguments,0);
    return function result() {
        return fns.reduceRight(
            function (prev,cur){
                return [cur.apply(this,prev)];
            },
            arguments
        )[0];
    };
}

これを「これを意識した」ものにしたいので、作成されている関数は、によって返される関数composeが呼び出されるコンテキストで呼び出されます。現在、これらはグローバルオブジェクトのコンテキストで呼び出されているようです。var self=this;関数の先頭で古いものを実行し、それを現在の呼び出しresultの最初の引数として使用できますが、引数を取る場合は不要です。cur.applythisreducethisArg

私はここで何かが足りないのですか、そしてreduceそれがこれを不必要または役に立たないものにする何かがありますか?

アップデート

@kangaxはい、それは私に起こりました。APIの設計を批判することは私からはほど遠いですが、の署名はreduce私には少し奇妙に思えます。2番目のオプションの引数は、通常はデフォルト値を持つ通常のオプションの引数とは機能が異なります。代わりに、その存在または不在によって動作が変更され、基本的にシグネチャ(引数数)に基づいて関数がオーバーロードされます。2番目のパラメーターがない場合、配列の最初の要素が開始値になり、コールバックへの最初の呼び出しは2番目の値に対して行われます。この動作は、呼び出すだけで簡単にエミュレートできるようです。

array.slice(1).reduce(fn,array[0])

2番目の引数が省略された場合の特別なルールを組み込む代わりに、推定が正しければ、引数を指定する場所を特定することも本質的に不可能になりthisArgます。繰り返しになりますが、仕様がハッシュ化されている間、そのような問題はすでに議論されていたと確信しています。そのようなアプローチには正当な理由があるかもしれません。

4

4 に答える 4

5

あなたはいつでもこの方法を使うことができます:

array.reduce(callback.bind(context), initialValue);

...特定のコンテキストをコールバック関数にアタッチするため。

于 2017-03-21T13:18:33.667 に答える
4

Es-discussメーリングリストでは、回答 http://article.gmane.org/gmane.comp.lang.javascript.ecmascript4.general/4770にあります。

コールバックを使用する他のメソッドは、「thisArg」を使用します。これは、これらの関数を提供する既存の実装ですでに実行されているため、必要または有用であるためではなく、互換性のためです。

于 2013-02-16T15:03:12.500 に答える
4

reduceRight)はすでに2つの機能(ウィキペディアを参照)をカバーしているため、2つのオプションの引数で混乱します。これらは純粋な言語(たとえば、名前付きfoldlfoldl1Haskell)で区別されます。ブレンダン・アイクを引用するには:

したがって、これは、reduceが1つのコールバック引数と2つのオプションの引数(thisObjectとinit)を取ることを意味します。どちらが先に来るべきですか?より一般的なものはおそらくinitですが、コールバック引数を「thisObject」引数から分離します。これはおそらく問題ありません。複数のオプションの引数は、このようにちょっと面倒です...

あるいは、人々はいつでも[バインディングを使用]できるので、余分な「thisObject」引数を削除することもできます。

これらの機能的な高階関数は、とにかく(あなたの例のように)lamdba -function-expressionsで主に使用されるため、これは大きな問題ではないと思います。もちろん、少し矛盾がありますが、私たちはそれで生きることができます。代替案をイメージしてください:

 array.reduce(callback[, initialValue[, thisArg]])

実際には使用できません。「initialValueが提供されたかどうか」を実際に判断することはできません。つまり、文字通りarguments.length < 2渡すこともできるからです。undefinedつまり、

 array.reduce(callback[, thisArg[, initialValue]])

初期値だけが必要な場合はnull、常に渡す必要があるため、これは醜いです。thisArg

Kangaxへのコメントですでに気づきましたが(「2番目のオプションの引数は通常のオプションの引数とは機能が異なります。[…]その存在または不在によって動作が変わります」)、私はあなたのステートメントをサポートできません

この動作は、呼び出すだけで簡単にエミュレートできます。array.slice(1).reduce(fn,array[0])

それは、a)変数の代わりに複雑な(連鎖した)式では機能せずarray、b)面倒です。

于 2013-02-16T17:37:08.713 に答える
1

thisObject引数は必要ありません。これは、アキュムレータにある種のthisObjectを追加し、初期値を使用してthisObjectを渡すことができるためです。

例:

thisObj = { some data }  // kind of this arg to be used in the reducer
const { view, used, totals } = sheetConfig.reduce(reducer, {
  view: [],    // initial  
  used: [],    // another initial
  totals: [],  // and one more initial
  thisObj      // and ...
});
于 2021-11-13T16:11:15.567 に答える