JuanBonnett
JuanBonnett

Reputation: 786

Javascript - function with optional parameters as object?

I need a function that its parameter is an object, and if I leave it empty it will load default values.

something like:

function loadMap(args) { //args is an object and its optional

   //this is what I want to do, test args and load defauts if necesary
   /*
   pseudocode:
   if args.latitude is not set then
       give it a default value

   if args.longitude is not set then
       give it a default value

    end pseudocode */

   alert("Latitude is "+args.latitude );
   alert("Longitude is "+args.longitude );
}

//outputs the default values
loadMap();

//outputs custom values
loadMap({latitude: "x.xxxx", longitude: "-x.xxxx"});

//and should work too and output one default and one custom value
loadMap({latitude: "x.xxxx"});

I found this solution in this question (Is there a better way to do optional function parameters in Javascript?) but it requires jQuery: http://jsfiddle.net/xy84kwdv/

It's ALMOST what I want but I don't want to depend on a jquery function.

Upvotes: 11

Views: 24137

Answers (8)

Tristan Collicott
Tristan Collicott

Reputation: 31

Ran into this problem because I wanted a default configuration object with many properties. So, destructuring in the function argument was out of the question.

Spread syntax does have some caveats. But it's unlikely complex objects that cause issues are going to be passed as optional arguments.

let defaultArgs = { lat: 'x.xxxx', lng: 'x.xxxx' };
function loadMap(args) {
  let { lat,lng } = { ...defaultArgs, ...args };
  console.log(`Lat: ${lat} Lng: ${lng}`)
}
loadMap();
loadMap({ lat: 1.2345 });
loadMap({ lat: 1.2345, lng: 1.2345 });

Console Logs:

Lat: x.xxxx Lng: x.xxxx
Lat: 1.2345 Lng: x.xxxx
Lat: 1.2345 Lng: 1.2345

Upvotes: 1

ztvmark
ztvmark

Reputation: 1434

Uses "??" instead of "||" or you may have errors in undefined or false variables

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator

function loadMap(args) { 
    args = args ?? {}; 
    args.latitude = args.latitude ?? "X.XXX"; 
    args.longitude = args.longitude ?? "Y.YYY"; 
    alert(args.latitude);
    alert(args.longitude);
}; 

loadMap({latitude:"custom_latitude"});

Upvotes: 1

ok_anthony
ok_anthony

Reputation: 41

Fisher's answer should be the accepted answer. Also, if you want to rename any of the destructured variables while still maintaining default values, you can do like so:

function findByCoordinates({coordinates: cords = {x: 0, y: 0}} = {}) {
  console.log(cords);
  // Some calculation...
}

Upvotes: 0

Fisher
Fisher

Reputation: 379

Surely this question is over 3 years old now(2018-03-02). I searched about this topic but most of the questions I got and the answers ranked top are seemed like to be outdated, like this, this, this, or this.

Currently, lots of browsers support ES6/ECMAScript 2015(the 6th Edition of ECMAScript). For compatibility, you can use WebpackJs(or another packer) and BabelJs(or another compiler) to compile and pack your ES6 codes to ES5. And the ES6-version answer for this question may be Object Destructuring.

function drawES2015Chart({size = 'big', cords = {x: 0, y: 0}, radius = 25} = {}) {
    console.log(size, cords, radius);
    // do some chart drawing
}

drawES2015Chart({cords: {x: 18, y: 30}, radius: 30});

function fn(requiredArg, {optionalArg = 'Default Value', a = 1, b ={some: 'object'}} = {}){
    // Do with destructured values: requiredArg, optionalArg, a, and b.
    console.log(requiredArg, optionalArg, a, b);
}

so for your question, it will be:

function loadMap({latitude = "x.xxxx", longitude = "-x.xxxx"} = {}) {
    console.log('latitude is:', latitude, 'and longitude is:', longitude);
    console.log(`latitude is: ${latitude}, and longitude is: ${longitude}`);
}

// Call the function.
loadMap({latitude: "1.2345", longitude: "-6.7890"});

Upvotes: 35

Paul S.
Paul S.

Reputation: 66324

Overkill, introduce full blown Object cloning (ECMAScript 5.1)

function cloneOwnProperties(A, B, overwrite) { // this is shallow
    var i, p;
    if (!(A instanceof Object)) {
        if (undefined === A) A = {};
        else throw new TypeError('cloneOwnProperties called on non-object');
    }
    if (!B) B = {};
    p = Object.getOwnPropertyNames(A);
    for (i = 0; i < p.length; ++i)
        if (overwrite || !(p[i] in B))
            Object.defineProperty(B, p[i], Object.getOwnPropertyDescriptor(A, p[i]));
    return B;
}

// and for completeness
function cloneObject(obj_in, clone_seal, clone_frozen) {
    var obj_out;
    if (!(obj_in instanceof Object))
        throw new TypeError('cloneObject called on non-object');
    obj_out = Object.create(Object.getPrototypeOf(obj_in));
    cloneOwnProperties(obj_in, obj_out, true);
    if (clone_seal && Object.isSealed(obj_in)) Object.seal(obj_out);
    if (clone_frozen && Object.isFrozen(obj_in)) Object.freeze(obj_out);
    return obj_out;
}
// back on topic

Now you can use it to set some defaults

function foo(bar) {
    bar = cloneOwnProperties(bar, {
        fizz: true,
        buzz: false
    }, true);
    return bar;
}

foo({buzz: 'user_value'}); // {fizz: true, buzz: "user_value"}

Upvotes: -1

Barmar
Barmar

Reputation: 780889

This makes the argument object optional, as well as making individual properties optional:

var defaults = { latitude: x, longitude: y };
function loadMap(args) {
    args = args || {};
    for (var key in defaults) {
        if (!(key in args)) {
            args[key] = default[key];
        }
    }
    ...
}

Upvotes: 4

user4411139
user4411139

Reputation:

How to overload functions in javascript? Check out the second answer to the OP. It offers an alternative to using jQ.

Note: Kim's code will result in a logical error if args passes but evaluates to true. A better fix: optionalArg = (typeof optionalArg === "undefined") ? "defaultValue" : optionalArg;

Upvotes: 0

Trace
Trace

Reputation: 18869

Are you looking for something like:

function loadMap(args) { 
    args = args || {}; 
    args.latitude = args.latitude || "X.XXX"; 
    args.longitude = args.longitude || "Y.YYY"; 
    alert(args.latitude);
    alert(args.longitude);
}; 

loadMap({latitude:"custom_latitude"});

Upvotes: 9

Related Questions