JavaScript参数和自定义选项作为参数有什么区别吗?

3

通过默认的 'arguments' 访问 javascript 参数和使用显式对象(例如 'options')之间有什么区别吗?

除了一个访问数组参数,另一个访问对象选项外,它们两个是否类似?

$.fn.myFn = function(){
  if arguments[0]//....
}

并且

$.fn.myFn = function(options){
  if options.value //....
}

2
在 ECMAScript 5 的 STRICT 模式下,arguments 是无效的。 - josh.trow
3
可以给我一个来源吗?我认为在ECMAScript 5中只有arguments.callerarguments.callee已经被弃用了。 - Ruan Mendes
@JuanMendes:你说得对,不过需要补充的是,嵌套函数现在无法访问其父级的 arguments 对象。 - josh.trow
主要的变化是在非严格模式下,如果你改变一个参数的值,它将会改变arguments中的值,反之亦然。例如:function add(num1){arguments[0] = 1;return num1;} add(5);//返回1这种奇怪的行为已经在ES5的严格模式中被移除了。 - Brian
6个回答

10
是的,它们很相似,但也有不同。如果不需要处理变量数量的话,我不会使用arguments,而是使用声明的参数和/或options对象。(此外,请注意,在大多数JavaScript引擎上,与使用声明的参数或甚至options对象相比,使用arguments伪数组[它实际上不是一个数组]会导致运行时速度惩罚。请参见下面的“附注”,尽管当然你必须在实际情况下频繁调用函数才能使开销成为问题。)
对于只接受几个参数的函数,使用声明的参数通常是有意义的,例如:
x = parseInt(str, 10);

如果 parseInt 使用一个选项风格的对象,那么你需要这样编写代码:
x = parseInt({string: str, radix: 10}); // Note: parseInt doesn't actually work this way

...或类似的方式,这会在每次调用时增加更多的打字工作。因此这是一个缺点。

但当你涉及到许多参数,特别是许多可选参数时,使用options模式,通过传递一个对象而不是离散的参数,可以获得真正的回报。考虑jQuery的ajax函数。它有约32个选项可以传递,几乎所有的选项都是可选的。就像你可能不想将每个parseInt编码为上面的示例一样,你可能不想将每个ajax调用编码成这样:

$.ajax(
    "/path/to/resource",
    function(data) {
    },
    undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined,
    undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined,
    undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined,
    undefined, undefined, undefined, undefined, undefined, undefined
);

我听说一个离散参数和选项式对象之间的经验法则是,当你有四个参数时,人们就会开始迷失方向。当然,你需要自己划定界限。

......也不例外。:-)


顺带一提:有关arguments比声明的参数慢,可以尝试这个测试。当然,调用开销大多数情况下并不重要,所以这并不重要。但是在那些时候,以下是我和其他人的结果:

enter image description here

正如您所看到的,对于几乎所有引擎来说,使用声明的参数是最快的。我甚至添加了一些比较arguments和传递数组的东西,对于那些需要可变数量参数的时候(答案:最好用数组)。

你说的“一些”,是指 IE 吧? - Dave
@Dave:我不会感到惊讶如果大多数引擎都存在性能损失,但有些引擎速度非常快,你可能无法察觉它。 :-) - T.J. Crowder

2

不同之处在于,在第一种情况下,arguments 是传递给函数的实际参数列表,而在第二种情况下,option 只是其中一个参数(arguments[0]),按照惯例它包含了实际的“arguments”。

与像 Python 这样的语言不同,Javascript 不提供内置的混合关键字和位置参数的方法。


为了使这些示例等效,您需要将第一个更改为arguments [0] .value。 - Dave

2
使用arguments会让函数运行变慢,但只有在你需要经常调用该函数时才会明显。仅在需要函数内部有可变参数时使用它。此外,如果不需要可变参数,使用arguments会使代码难以理解,因为你没有变量名。请注意保留HTML标签。

-1 是因为我对你关于性能的说法表示怀疑。如果你能提供支持,我会撤销这个负评。 - Gabe Moothart
@GabeMoothart:那你最好撤销它。:-)“arguments”比声明的参数慢是众所周知的,请在此处测试:http://jsperf.com/using-declared-arguments-vs-the-arguments-pseudo-array 使用“arguments.callee”会更慢。现在,如果你要使用“arguments”,你必须频繁地调用函数才会感觉到它的影响(使用“arguments.callee”则稍微好一些),但它确实比较慢。 - T.J. Crowder
@GabeMoothart: http://webreflection.blogspot.com/2010/02/arguments-callee-call-and-apply.html - Ruan Mendes
2
取消踩票。像“参数会使函数变慢”这样的建议仍然让我感到不好,因为它鼓励过早优化,但从技术上讲是正确的。 - Gabe Moothart
@GabeMoothart:是的,我会总是加上一句“不过你得频繁调用这个函数才有所影响”的警示。 - T.J. Crowder
@GabeMoothart:我没有说永远不要使用它。如果您需要支持可变参数,那么这是唯一的方法。问题在于差异,这就是一个差异。对我来说,过度优化是指遵循比直接完成某些任务更需要维护的(反)模式。不使用arguments 不是过度优化,但是在不需要时使用它只会使您的代码更难读懂。 - Ruan Mendes

1
正式来说,区别在于 $.fn.myFn.length 的值为 0 或者 1(因为在第一种情况下函数定义时没有参数,在第二种情况下函数定义时有 1 个参数),尽管你通常不需要这个属性。

除此之外,两者工作方式相同。


1

正如 @missigno 指出的那样,显然存在一些语法差异。但是,如果你问为什么要使用其中之一,显式对象方法是在 JavaScript 中提供命名参数的一种方式。

如果有大量参数,但大部分时间只需要指定其中几个,这可能非常有用。出于美学原因,有些人也更喜欢它 - 选项的名称出现在其值旁边,因此您不必仅仅知道例如第3个参数的作用。


1

基本上,arguments 允许您期望传递给函数的未知数量的参数。一个快速的例子是在 GetSum() 函数中,它返回您一次性传递给它的所有数字的总和。

另一方面,options 允许您为函数指定命名参数,而不需要显式顺序。这在扩展现有函数时特别方便,无需担心与严格函数签名的冲突/向后兼容性。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接