3

is there a difference accessing javascript arguments via the default 'arguments' and using an explicit object such as 'options'?

are these two similar apart from that one accesses the array arguments and the other accesses the object options?

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

and

$.fn.myFn = function(options){
  if options.value //....
}
Pete_ch
  • 1,301
  • 2
  • 28
  • 39
  • 2
    Well `arguments` is invalid in STRICT mode, ECMAScript 5 – josh.trow Feb 08 '12 at 18:43
  • 3
    @josh.trow: Can you point to a source? I thought only `arguments.caller` and `arguments.callee` were deprecated in ECMAScript 5 – Ruan Mendes Feb 08 '12 at 18:48
  • @JuanMendes: You are right, with the addition that nested functions can no longer access their parents' `arguments` object. – josh.trow Feb 08 '12 at 18:56
  • The major change is that in non-strict mode, if you alter the value of an argument it will alter the value in `arguments`, and vice versa. For example: `function add(num1){arguments[0] = 1;return num1;} add(5);//returns 1` This strange behavior has been removed in strict mode in ES5. – Brian Feb 08 '12 at 19:07

6 Answers6

10

Yes, they're similar, but they're different as well. I wouldn't use arguments for anything that doesn't truly need to handle variable numbers of arguments; I'd use declared arguments and/or an options object. (Also note that on most JavaScript engines, using the arguments pseudo-array [it's not really an array] incurs a runtime speed penalty compared with using declared arguments, or even an options object. See "side note" below, though of course you have to call the function a lot for that overhead to matter in the real world.)

Using declared arguments for functions that accept only a couple of arguments usually makes sense, e.g.:

x = parseInt(str, 10);

If parseInt used an options-style object, you'd have to write that as:

x = parseInt({string: str, radix: 10}); // Note: parseInt doesn't actually work this way

...or similar, which is more typing on every call. So that's a downside.

But when you get into lots of arguments, and particularly lots of optional arguments, using the options pattern where you pass in an object instead of discrete arguments can have real payoffs. Consider the jQuery ajax function. It has ~32 options you can pass to it, nearly all of them optional. Just as you probably wouldn't want to code every parseInt as above, you probably wouldn't want to code every ajax call like this:

$.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
);

...either. :-)

One rule of thumb I've heard for discrete arguments vs. options-style objects is when you get to four arguments, people are going to start getting lost. You'll want to draw your own line, of course.


Side note: More about arguments being slower than declared args, try this test. Now of course, call overhead doesn't matter most of the time, so most of the time this doesn't matter. But for those times it does, here are the results from me and others:

enter image description here

As you can see, using declared arguments is the fastest by far on pretty much all engines. I even threw in something comparing arguments to passing in an array, for those times you really need a variable number of arguments (answer: you're better off with the array).

hugomg
  • 68,213
  • 24
  • 160
  • 246
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
2

The diference is that in the first case arguments is the actual list of arguents passed to the function and in the second case, option is just one of the arguments (arguments[0]) and it contains the actual "arguments" by convention.

Unlike languages like Python, Javascript does not provide buit-in ways of mixing keyword and positional arguments.

hugomg
  • 68,213
  • 24
  • 160
  • 246
  • For the the examples to be equivalent, you'd need to change the first one to arguments[0].value – Dave Feb 08 '12 at 18:44
2

Using arguments makes your function run slower but the difference is only noticeable if you're calling that function a lot. Only use it when you need variable arguments in your function. Also, using arguments when you don't need variable arguments makes it harder to understand since you don't have variable names.

Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217
  • -1 b/c I doubt your claim about performance. If you can support it I'll undo the downvote. – Gabe Moothart Feb 08 '12 at 18:50
  • @GabeMoothart: You'll want to undo that, then. :-) `arguments` being slower than declared arguments is well-known, test it here: http://jsperf.com/using-declared-arguments-vs-the-arguments-pseudo-array Using `arguments.callee` is ever slower. Now, with `arguments` you have to be calling the function a *lot* for it to matter (less so with `arguments.callee`), but it is slower. – T.J. Crowder Feb 08 '12 at 19:00
  • @GabeMoothart: http://webreflection.blogspot.com/2010/02/arguments-callee-call-and-apply.html – Ruan Mendes Feb 08 '12 at 19:02
  • 2
    un-downvoted. Advice such as "arguments makes your function slower" still strikes me as bad b/c it encourages premature optimization, but it is technically correct. – Gabe Moothart Feb 08 '12 at 19:31
  • @GabeMoothart: Yeah, I would always include the "but you'd have to be calling the function a **lot** for it to matter" caveat. – T.J. Crowder Feb 08 '12 at 19:32
  • @GabeMoothart: I didn't say don't ever use it. It's the only way if you need to support variable arguments. The question was about the difference, and that is one difference. To me, premature optimization is when you follow a (anti-)pattern that requires more maintenance than the straight forward way of doing something. Not using `arguments` is not premature optimization, but using it when not needed is just making your code harder to read. – Ruan Mendes Feb 08 '12 at 19:36
1

Formally, the difference is that $.fn.myFn.length is either 0 or 1 (because the function is defined with 0 arguments in the first case and 1 argument in the second case), although you normally don't need this property.

Other than that, both work equally.

pimvdb
  • 151,816
  • 78
  • 307
  • 352
1

Clearly there is some syntactic difference as @missigno points out. But if you're asking why should you do one or the other - the explicit-object method is a way to provide named parameters in javascript.

This can be useful if you can have a large number of arguments, but only a few need to be specified most of the time. Some people also prefer it for aesthetic reasons - the name of the option appears alongside its value so you don't have to just know what, for example, argument 3 does.

Gabe Moothart
  • 31,211
  • 14
  • 77
  • 99
1

Basically, arguments allows you to expect an unknown number of arguments passed to your function. A quick top-of-head example is in a GetSum() function which returns the total sum of all numbers you pass into it in one go.

options, on the other hand, allows you to specify named arguments to your function, without an explicit order. This is especially handy, for example, when extending existing functions without having to worry about collision / backwards compatibility with strict function signatures.

Richard Neil Ilagan
  • 14,627
  • 5
  • 48
  • 66