多个参数与选项对象

2022-08-30 01:33:28

在创建具有多个参数的JavaScript函数时,我总是面临这样的选择:传递参数列表与传递选项对象。

例如,我正在编写一个函数来将 nodeList 映射到数组:

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

我可以改用这个:

function map(options){
    ...
}

其中选项是一个对象:

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

哪一种是推荐的方式?是否有关于何时使用一个与另一个的指南?

[更新]似乎有一个支持选项对象的共识,所以我想添加一个注释:在我的情况下,我试图使用参数列表的一个原因是要有一个与JavaScript内置的array.map方法一致的行为。


答案 1

像许多其他人一样,我经常更喜欢将a传递给函数,而不是传递一长串参数,但这实际上取决于确切的上下文。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
 });

它更像是一门艺术,而不是一门科学,但如果我必须说出经验法则:

在以下情况下使用选项参数:

  • 您有四个以上的参数
  • 任何参数都是可选的
  • 您曾经必须查找该函数以找出它需要哪些参数
  • 如果有人试图在尖叫“ARRRRRG”时勒死你!

答案 2

多个参数主要用于强制参数。他们没有错。

如果您有可选参数,则情况会变得复杂。如果其中一个依赖于其他参数,以便它们具有一定的顺序(例如,第四个需要第三个),您仍然应该使用多个参数。几乎所有的原生 EcmaScript 和 DOM 方法都是这样工作的。一个很好的例子是XMLHTTPrequests的开放方法,其中最后3个参数是可选的 - 规则类似于“没有用户就没有密码”(另请参阅MDN文档)。

选项对象在两种情况下派上用场:

  • 你有这么多的参数,它变得令人困惑:“命名”会帮助你,你不必担心它们的顺序(特别是如果它们可能会改变)
  • 您有可选参数。对象非常灵活,没有任何顺序,你只需要传递你需要的东西,而没有其他东西(或多个)。undefined

就您而言,我建议. 并且是必需的,其他三个参数只是偶尔出现并且具有合理的默认值。map(nodeList, callback, options)nodelistcallback

另一个例子是JSON.stringify。您可能希望在不传递函数的情况下使用该参数 - 然后您必须调用 。参数对象可能更好,尽管它对于仅 2 个参数来说并不真正合理。spacereplacer…, null, 4)