187

複数の引数を持つ JavaScript 関数を作成するとき、私は常に次の選択に直面します。引数のリストを渡すか、オプション オブジェクトを渡すかです。

たとえば、nodeList を配列にマップする関数を作成しています。

function map(nodeList, callback, thisObject, fromIndex, toIndex){
    ...
}

代わりにこれを使用できます:

function map(options){
    ...
}

options はオブジェクトです:

options={
    nodeList:...,
    callback:...,
    thisObject:...,
    fromIndex:...,
    toIndex:...
}

おすすめの方法はどれ?どちらか一方をいつ使用するかについてのガイドラインはありますか?

[更新] options オブジェクトを支持するコンセンサスがあるようですので、コメントを追加したいと思います: 私の場合に引数のリストを使用するように誘惑された理由の 1 つは、JavaScript と一貫した動作をすることでした。 array.map メソッドに組み込まれています。

4

10 に答える 10

194

他の多くの場合と同様にoptions object、パラメーターの長いリストを渡すのではなく、関数にを渡す方が好きなことがよくありますが、実際には正確なコンテキストによって異なります。

私はリトマス試験としてコードの可読性を使用しています。

たとえば、この関数呼び出しがある場合:

checkStringLength(inputStr, 10);

コードはそのままでもかなり読みやすく、個々のパラメーターを渡すのは問題ないと思います。

一方、次のような呼び出しを持つ関数があります。

initiateTransferProtocol("http", false, 150, 90, null, true, 18);

あなたがいくつかの研究をしない限り、完全に読めません。一方、このコードはよく読みます:

initiateTransferProtocol({
  "protocol": "http",
  "sync":      false,
  "delayBetweenRetries": 150,
  "randomVarianceBetweenRetries": 90,
  "retryCallback": null,
  "log": true,
  "maxRetries": 18
 });

それは科学というよりは芸術ですが、経験則に名前を付ける必要がある場合は、次のようになります。

次の場合は、オプションパラメータを使用します。

  • 4つ以上のパラメータがあります
  • パラメータのいずれかはオプションです
  • 関数を調べて、必要なパラメーターを把握する必要がありました。
  • 「ARRRRRG!」と叫びながら誰かがあなたを絞め殺そうとした場合。
于 2012-10-10T19:47:36.107 に答える
34

複数の引数は、主に必須パラメーター用です。彼らには何の問題もありません。

オプションのパラメータがあると、複雑になります。それらの 1 つが他のものに依存し、特定の順序 (たとえば、4 番目の引数が 3 番目の引数を必要とするなど) を持つ場合でも、複数の引数を使用する必要があります。ほとんどすべてのネイティブ EcmaScript および DOM メソッドは、このように機能します。良い例はopenXMLHTTPrequests のメソッドで、最後の 3 つの引数はオプションです。ルールは「ユーザーなしではパスワードなし」のようなものです ( MDN docsも参照)。

オプション オブジェクトは、次の 2 つの場合に役立ちます。

  • パラメータが多すぎて混乱します: 「命名」が役に立ちます。それらの順序を気にする必要はありません (特に、パラメータが変更される可能性がある場合)。
  • オプションのパラメーターがあります。オブジェクトは非常に柔軟で、順序付けなしで、必要なものだけを渡すだけですundefined

あなたの場合、私はお勧めしmap(nodeList, callback, options)ます。nodelistおよびcallback必須ですが、他の 3 つの引数はたまにしか使用されず、適切なデフォルトが設定されています。

別の例ですJSON.stringifyspace関数を渡さずにパラメーターを使用したい場合があります。replacerその場合は、 を呼び出す必要があります…, null, 4)。引数オブジェクトの方が優れているかもしれませんが、2 つのパラメーターだけではあまり合理的ではありません。

于 2012-10-10T19:56:42.477 に答える
12

「オブジェクトとしてのオプション」アプローチを使用するのが最善です。プロパティの順序を気にする必要がなく、渡されるデータの柔軟性が向上します (オプションのパラメーターなど)。

オブジェクトを作成すると、複数の関数でオプションを簡単に使用できることも意味します。

options={
    nodeList:...,
    callback:...,
    thisObject:...,
    fromIndex:...,
    toIndex:...
}

function1(options){
    alert(options.nodeList);
}

function2(options){
    alert(options.fromIndex);
}
于 2012-10-10T19:37:05.233 に答える
11

両方使うのもいいかもしれません。関数に 1 つまたは 2 つの必須パラメーターと一連のオプションのパラメーターがある場合は、最初の 2 つのパラメーターを必須にし、3 つ目をオプションのオプション ハッシュにします。

あなたの例では、私はそうしますmap(nodeList, callback, options)。Nodelist と callback が必要です。それへの呼び出しを読み取るだけで、何が起こっているかを簡単に知ることができます。これは、既存の map 関数のようなものです。その他のオプションは、オプションの 3 番目のパラメーターとして渡すことができます。

于 2012-10-10T19:55:23.687 に答える
7

質問に対するあなたのコメント:

私の例では、最後の3つはオプションです。

では、なぜこれをしないのですか? (注:これはかなり生のJavascriptです。通常はハッシュを使用し、 Object.extendJQuery.extenddefaultなどを使用して渡されたオプションで更新します。)

function map(nodeList, callback, options) {
   options = options || {};
   var thisObject = options.thisObject || {};
   var fromIndex = options.fromIndex || 0;
   var toIndex = options.toIndex || 0;
}

つまり、オプションであるものとそうでないものがはるかに明確になったので、これらはすべて関数の有効な使用法です。

map(nodeList, callback);
map(nodeList, callback, {});
map(nodeList, callback, null);
map(nodeList, callback, {
   thisObject: {some: 'object'},
});
map(nodeList, callback, {
   toIndex: 100,
});
map(nodeList, callback, {
   thisObject: {some: 'object'},
   fromIndex: 0,
   toIndex: 100,
});
于 2012-10-11T02:47:16.590 に答える
4

場合によります。

これらの一般的なライブラリの設計に関する私の観察に基づいて、オプション オブジェクトを使用する必要があるシナリオを次に示します。

  • パラメータ リストが長い (>4)。
  • 一部またはすべてのパラメーターはオプションであり、特定の順序に依存しません。
  • パラメーター リストは、将来の API 更新で拡張される可能性があります。
  • API は他のコードから呼び出され、API 名はパラメーターの意味を伝えるのに十分明確ではありません。そのため、読みやすくするために強力なパラメーター名が必要になる場合があります。

パラメータリストを使用するシナリオ:

  • パラメータ リストが短い (<= 4)。
  • パラメータのほとんどまたはすべてが必須です。
  • オプションのパラメーターは特定の順序になっています。(つまり: $.get )
  • パラメータの意味をAPI名で分かりやすく。
于 2013-04-15T19:31:55.667 に答える
2

オブジェクトを渡すと、そのオブジェクトのプロパティの数を簡単に拡張でき、引数が渡された順序を監視する必要がないため、オブジェクトの方が望ましいです。

于 2012-10-10T19:37:10.073 に答える
1

通常、定義済みの引数を使用する関数の場合は、オプション オブジェクトを使用することをお勧めします。反対の例は、setCSS({height:100},{width:200},{background:"#000"}) のように無限の数の引数を取得する関数のようなものです。

于 2012-10-10T19:56:10.900 に答える
0

私は大規模なJavaScriptプロジェクトを検討します。

インスタンス化されたオブジェクトにはオブジェクトが必要ですが、関数にはパラメーターが必要であることがよくわかります。これは OPTION 引数に関係していると思います。

デフォルトの引数またはオプションの引数が必要な場合は、より柔軟なオブジェクトの方がよいでしょう。ただし、通常の関数引数を使用しない場合は、より明示的になります。

Javascript にもargumentsオブジェクトがあります。 https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments

于 2012-10-10T19:36:53.143 に答える