Categories
arguments default-parameters function javascript parameters

Set a default parameter value for a JavaScript function

2585

I would like a JavaScript function to have optional arguments which I set a default on, which get used if the value isn’t defined (and ignored if the value is passed). In Ruby you can do it like this:

def read_file(file, delete_after = false)
  # code
end

Does this work in JavaScript?

function read_file(file, delete_after = false) {
  // Code
}

0

    3502

    From ES6/ES2015, default parameters are in the language specification.

    function read_file(file, delete_after = false) {
      // Code
    }
    

    just works.

    Reference: Default Parameters – MDN

    Default function parameters allow formal parameters to be initialized with default values if no value or undefined is passed.

    In ES6, you can simulate default named parameters via destructuring:

    // the `= {}` below lets you call the function without any parameters
    function myFor({ start = 5, end = 1, step = -1 } = {}) { // (A)
        // Use the variables `start`, `end` and `step` here
        ···
    }
    
    // sample call using an object
    myFor({ start: 3, end: 0 });
    
    // also OK
    myFor();
    myFor({});
    

    Pre ES2015,

    There are a lot of ways, but this is my preferred method — it lets you pass in anything you want, including false or null. (typeof null == "object")

    function foo(a, b) {
      a = typeof a !== 'undefined' ? a : 42;
      b = typeof b !== 'undefined' ? b : 'default_b';
      ...
    }
    

    22

    • 226

      You can also encapsulate it as such: function defaultFor(arg, val) { return typeof arg !== 'undefined' ? arg : val; } and then you can call it as a = defaultFor(a, 42);

      Sep 2, 2012 at 5:56


    • 7

      @SiPlus and you got extra reference errors for free of charge while trying to use undefined objects :p Even while it may work with some browsers and might be faster, null is still an object and undefined is reference to primitive type that is trying to tell that there is nothing here, not even null. See here, both cases in nutshell: JavaScript/Reference/Global_Objects/undefined.

      Nov 3, 2012 at 1:29


    • 10

      if you check against the property of an object, then typeof is redundant. function foo(data) { var bar = data.bar !== undefined ? data.bar : 'default'; } This won’t throw reference errors and is concise.

      – Dziamid

      May 17, 2013 at 11:06


    • 12

      I know it’s really minor, but I don’t like how you are assigning a = a and b = b when those parameters are not undefined. Also, that ternary operator with a bit complicated condition may be hard to read for future maintainers. I would prefer following syntax: if (typeof a == 'undefined') a = 42 – no unnecessary assignment plus a little bit easier to read.

      – Daddy32

      Dec 9, 2014 at 15:31


    • 13

      Is there any reason to use typeof? It would seem simpler to just do a === undefined. Plus that way you’d get a reference error if you misspelled undefined vs. putting it in a string.

      May 21, 2015 at 22:04


    625

    function read_file(file, delete_after) {
        delete_after = delete_after || "my default here";
        //rest of code
    }
    

    This assigns to delete_after the value of delete_after if it is not a falsey value otherwise it assigns the string "my default here". For more detail, check out Doug Crockford’s survey of the language and check out the section on Operators.

    This approach does not work if you want to pass in a falsey value i.e. false, null, undefined, 0 or "". If you require falsey values to be passed in you would need to use the method in Tom Ritter’s answer.

    When dealing with a number of parameters to a function, it is often useful to allow the consumer to pass the parameter arguments in an object and then merge these values with an object that contains the default values for the function

    function read_file(values) {
        values = merge({ 
            delete_after : "my default here"
        }, values || {});
    
        // rest of code
    }
    
    // simple implementation based on $.extend() from jQuery
    function merge() {
        var obj, name, copy,
            target = arguments[0] || {},
            i = 1,
            length = arguments.length;
    
        for (; i < length; i++) {
            if ((obj = arguments[i]) != null) {
                for (name in obj) {
                    copy = obj[name];
    
                    if (target === copy) {
                        continue;
                    }
                    else if (copy !== undefined) {
                        target[name] = copy;
                    }
                }
            }
        }
    
        return target;
    };
    

    to use

    // will use the default delete_after value
    read_file({ file: "my file" }); 
    
    // will override default delete_after value
    read_file({ file: "my file", delete_after: "my value" }); 
    

    14

    • 121

      I find this insufficient, because I may want to pass in false.

      May 21, 2009 at 20:11

    • 53

      I find it’s adequate for most situations

      – Russ Cam

      May 21, 2009 at 20:16

    • 53

      Because it doesn’t work for falsey values, it may create a maintenance nightmare. A bit of code that has always been passed truthy values before and suddenly fails because a falsey one is passed in should probably be avoided where a more robust approach is available.

      Oct 31, 2012 at 20:34

    • 1

      How come, in this case, delete_after doesn’t get the boolean result of the expression delete_after || "my default value"?

      – Ayush

      Nov 28, 2012 at 5:56


    • 3

      or, you could just default to a falsey value – which is generally a good default anyway (eg., false for bools, empty string for strings, 0 for numbers, etc.) – in which case it doesn’t really matter what was passed in.

      Mar 27, 2016 at 1:33

    156

    I find something simple like this to be much more concise and readable personally.

    function pick(arg, def) {
       return (typeof arg == 'undefined' ? def : arg);
    }
    
    function myFunc(x) {
      x = pick(x, 'my default');
    } 
    

    7

    • 6

      Update: If you’re using underscore.js already I find it even better to use _.defaults(iceCream, {flavor: "vanilla", sprinkles: "lots"});. Using the global namespace as shown in this answer is by many considered a bad practice. You may also consider rolling your own utility for this common task (eg. util.default(arg, "defaul value")) if don’t want to use underscore, but I mostly end up using underscore sooner or later anyway no point in reinventing the wheel.

      – andersand

      Aug 15, 2014 at 20:12


    • 2

      I actually recommend this one, i use it and call it “por” which stands for “parameter or”

      – user2039981

      Apr 21, 2015 at 16:59


    • 2

      Don’t say typeof arg == ‘undefined’, instead say arg === undefined

      Oct 20, 2015 at 15:06

    • 3

      @OsamaBinLogin what you say is correct for current JS – the older test persists because on some browsers it used to be possible to overwrite undefined with some other value, causing the test to fail.

      – Alnitak

      Nov 16, 2015 at 11:34

    • 2

      @Alnitak: It’s still possible to override undefined. So, it’s still a good idea to use typeof and 'undefined'.

      Jun 14, 2017 at 20:27