11

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.

8 Answers 8

36

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"});
Sign up to request clarification or add additional context in comments.

1 Comment

Sweet! Thanks! From the MDN link you posted: I was wondering why would I needed the empty {} at the right hand side. According to the docs: You could have also written the function without the right-hand side assignment. However, if you leave out the right-hand side assignment, the function will look for at least one argument to be supplied when invoked, whereas in its current form, you can simply call drawES2015Chart() without supplying any parameters
9

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"});

6 Comments

jsfiddle.net/f5nqnwc1 - as you can see that wouldn't behave as expected if you pass only ONE custom value and leave the rest empty
I tested it. And it's working perfectly... the code is clean, there is nothing complicated unlike the other 10000 algorithms out there to achieve the same... Your solution is the best so far!
This will mess up loadMap({latitude: 0})
Ah yea... we're talking about 0 being like FALSE... it's ok, we can work it out
It's ok... nothing I can't fix with some ternary operations!
|
4

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];
        }
    }
    ...
}

1 Comment

I added a comment but I didn't read your answer well... This seems to work too, and it's very clean
1

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"});

Comments

1

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

Comments

0

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;

1 Comment

Don't post link-only answers. Flag the question as a duplicate.
0

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...
}

Comments

-1

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"}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.