Search code examples
javascriptfunctiondefault

Javascript default parameters in functions with multiple arguments


I have a function that takes multiple optional arguments. Currently the function isn't assigning default values in the manner I expect.

var test1 = function(arg1, arg2, arg3, arg4) {

    arg1 = arg1 || "arg1";
    arg2 = arg2 || "arg2";

    var obj = {
      arg1: arg1,
      arg2: arg2,
      arg3: arg3,
      arg4: arg4
    };

    return(obj);

};

var obj1 = test1(arg3 = "notarg1", arg4 = "notarg2"); // Why are these values assigned to arg1 & arg2 instead of 3 & 4?

console.log(obj1);

I don't understand this. Javascript seems to ignore my (arg3 = "notarg1", arg4 = "notarg2") assignments and instead behaves as though (arg1 = "notarg1", arg2 = "notarg2", arg3 = undefined, arg4 = undefined) was my input.

  var test2 = function(arg1, arg2, arg3, arg4) {

    if (arg1 === null) {
      arg1 = "arg1";
    }
    if (arg2 === null || arg2 === "undefined") {
      arg2 = "arg2";
    }

    var obj = {
      arg1: arg1,
      arg2: arg2,
      arg3: arg3,
      arg4: arg4
    };

    return(obj);

  };

  var obj2 = test2(arg3 = "notarg1", arg4 = "notarg2")

  console.log(obj2);

I'm not sure if this is worth including. The situation doesn't change.


Solution

  • JavaScript doesn't have a feature for naming the argument you're specifying when calling a function, so this line:

    var obj1 = test1(arg3 = "notarg1", arg4 = "notarg2");
    

    ...doesn't do what you think it does. It does this:

    arg3 = "notarg1";
    arg4 = "notarg2";
    var obj1 = test1("notarg1", "notarg2");
    

    E.g., the arg3 = "notarg1" in the function call is just an assignment to a variable (in this case, probably an implicit global), and the way the assignment operator works is that it assigns the value and the result of the operation is the value that was assigned.

    To get the default for args 1 and 2, using your code, you'd have to specify undefined:

    var obj1 = test1(undefined, undefined, arg3, arg4);
    

    There, you are specifying args 1 and 2, but the value you're giving them is falsey, and so your function's arg1 = arg1 || "arg1" will take "arg1" (and similarly for arg2).

    If you have more than about three arguments, you might look at using options objects instead:

    function test1(options) {
        var arg1 = options.arg1 || "arg1";
        var arg2 = options.arg2 || "arg2";
        var arg3 = options.arg3 || "arg3";
        var arg4 = options.arg4 || "arg4";
    
        console.log(arg1, arg2, arg3, arg4)
    }
    
    test({arg3: "notarg1", arg4: "notarg2"});
    

    Output:

    arg1, arg2, notarg1, notarg2
    

    Just for completeness, ES2015 (aka ES6) adds default argument values, but you still can't call the function the way you showed in your question. The ES2015 syntax does simplify the code in your function, though.

    // ES2015+
    function test1(arg1 = "arg1", arg2 = "arg2", arg3, arg4) {
        // ....
    }
    

    Again, though, what you do when calling it is the same, there's still no special "matching up the names" feature as there is in some languages.