2

Observe:

function myFunc(arg1, arg2) {
  if (arguments.length < 2) { // Only one argument received
    arg1 = "Default"; // Set arg1 to some default value
    arg2 = arguments[0]; // Use the first argument passed for arg2
  }
  return [arg1, arg2];
}

myFunc("Hello", "World"); //=> ["Hello", "World"]

// So far, so good. Now let's try one that uses the default value for arg1:

myFunc("World"); //=> ["Default", "Default"]

What the heck, JavaScript? What's going on here? Why does JavaScript behave this way?

2
  • 1
    @MIIB It's a special variable in JavaScript which is basically an object containg all arguments passed to a function: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Commented Mar 4, 2014 at 21:58
  • so why dont you just put arg1 to arg2 and then change arg1 to default. Then what hapends? :P Commented Mar 4, 2014 at 21:59

3 Answers 3

17

You are overwriting your first argument before using its value:

arg1 = "Default"; // Set arg1 to some default value
arg2 = arguments[0]; // Use the first argument passed for arg2

So the value of arg2 is set to the value "Default" rather than the original value.

Sign up to request clarification or add additional context in comments.

3 Comments

Noting that any named arguments given values are getters/setters for their respective entry in arguments, which is why setting arg1 affects arguments[0].
Correct, Jonathan, thank you. OP, your question states you want an explanation of the behavior. Is the explanation above sufficient or do you want a workaround as well?
Wow, that's confusing behavior. Thanks, that explains the "what" part. And it looks like @Jacob Krall sort of explained the "why" in his answer below.
5

Try switching the logic in your if statement:

function myFunc(arg1, arg2) {
  if (arguments.length < 2) { // Only one argument received
    arg2 = arguments[0]; // Use the first argument passed for arg2
    arg1 = "Default"; // Set arg1 to some default value
  }
  return [arg1, arg2];
}

1 Comment

Yeah, 30 seconds can matter that much!
3

It's part of the spec:

For non-strict mode functions the array index (defined in 15.4) named data properties of an arguments object whose numeric name values are less than the number of formal parameters of the corresponding function object initially share their values with the corresponding argument bindings in the function’s execution context. This means that changing the property changes the corresponding value of the argument binding and vice-versa. This correspondence is broken if such a property is deleted and then redefined or if the property is changed into an accessor property. For strict mode functions, the values of the arguments object’s properties are simply a copy of the arguments passed to the function and there is no dynamic linkage between the property values and the formal parameter values.

Note that your function works as expected if you "use strict";.

3 Comments

Ah, the spec. Thanks, that's perfect. I wonder what was going through the language designer's heads when they decided that would be reasonable behavior. O.o
If I had to guess, I'd say it was for ease of implementation. That is: named arguments are implemented as indexes into arguments[]
This is the correct answer here, using strict mode.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.