多个参数与选项对象

时间:2012-10-10 19:34:25

标签: javascript json function object arguments

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

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

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

我可以改用:

function map(options){
    ...
}

其中options是一个对象:

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

推荐哪种方式?是否存在何时使用其中一种与另一种相比的指南?

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

8 个答案:

答案 0 :(得分:137)

与其他许多人一样,我经常更喜欢将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!”时扼杀你,

答案 1 :(得分:11)

使用'选项作为对象'方法将是最好的。您不必担心属性的顺序,并且可以更灵活地传递数据(例如,可选参数)

创建对象也意味着可以在多个函数上轻松使用这些选项:

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

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

function2(options){
    alert(options.fromIndex);
}

答案 2 :(得分:9)

我认为如果你要实例化某个东西或者调用一个对象的方法,你想要使用一个options对象。如果它是仅对一个或两个参数进行操作并返回值的函数,则最好使用参数列表。

在某些情况下,使用两者都很好。如果你的函数有一个或两个必需参数和一堆可选参数,那么需要前两个参数,第三个是可选选项hash。

在您的示例中,我会map(nodeList, callback, options)。需要节点列表和回调,只需通过读取它就可以很容易地判断发生了什么,就像现有的地图功能一样。任何其他选项都可以作为可选的第三个参数传递。

答案 3 :(得分:7)

您对该问题的评论:

  

在我的例子中,最后三个是可选的。

那么为什么不这样做呢? (注意:这是相当原始的Javascript。通常我会使用default哈希值,并使用Object.extendJQuery.extend或类似内容传入的选项对其进行更新。 。)

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,
});

答案 4 :(得分:3)

这取决于。

基于我对那些流行的库设计的观察,以下是我们应该使用选项对象的场景:

  • 参数列表很长(> 4)。
  • 部分或全部参数是可选的,它们不依赖于某些参数 顺序。
  • 参数列表可能会在未来的API更新中增加。
  • 将从其他代码调用API,并且API名称不清楚 足以告诉参数的含义。所以它可能需要强大 参数名称的可读性。

使用参数列表的场景:

  • 参数列表很短(< = 4)。
  • 大多数或所有参数都是必需的。
  • 可选参数按特定顺序排列。 (即:$ .get)
  • 通过API名称轻松告知参数含义。

答案 5 :(得分:2)

对象是更可取的,因为如果你传递一个对象,那么它很容易在这些对象中扩展属性数,你不必注意你的参数传递的顺序。

答案 6 :(得分:2)

对于这个回复我可能有点迟到了,但我正在寻找其他开发人员对这个主题的意见并且遇到了这个主题。

我非常不同意大多数响应者,并且采用“多参数”方法。我的主要论点是它不鼓励其他反模式,如“变异和返回param对象”,或“将相同的param对象传递给其他函数”。我曾在代码库中工作,这些代码库广泛滥用了这种反模式,调试代码很快就变得不可能。我认为这是一个特定于Javascript的经验法则,因为Javascript不是强类型的,并允许这种任意结构化的对象。

我个人认为开发人员在调用函数时应该是明确的,避免传递冗余数据并避免通过引用修改。并不是说这种模式排除了编写简洁,正确的代码。我只是觉得它让你的项目更容易陷入糟糕的开发实践。

考虑以下可怕的代码:

function main() {
    const x = foo({
        param1: "something",
        param2: "something else",
        param3: "more variables"
    });

    return x;
}

function foo(params) {
    params.param1 = "Something new";
    bar(params);
    return params;
}


function bar(params) {
    params.param2 = "Something else entirely";
    const y = baz(params);
    return params.param2;
}

function baz(params) {
    params.params3 = "Changed my mind";
    return params;
}

这种类型不仅需要更明确的文档来指定意图,而且还为模糊错误留出了空间。 如果开发人员修改param1中的bar()怎么办?您认为通过查看足够大小的代码库来捕获这个问题需要多长时间? 不可否认,这个例子有点不诚实,因为它假设开发人员已经提出了几个反模式。但它显示了包含参数的传递对象如何允许更大的错误和模糊性空间,需要更大程度的尽责和遵守const正确性。

这个问题只是我的两分钱!

答案 7 :(得分:0)

我会看一下大型的JavaScript项目。

谷歌地图之类的东西你会经常看到实例化的对象需要一个对象,但是函数需要参数。我认为这与OPTION争论有关。

如果您需要默认参数或可选参数,则对象可能会更好,因为它更灵活。但是,如果你没有正常的功能参数更明确。

Javascript也有一个arguments对象。 https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments