1

I am sure this has been answered before, but searching only yields results for passing an actual object as a function arguments, however I would like to destructure an object and use its parameters as input arguments for a function.

I am importing the function foo() from an external library and would like to supply its arguments using an object containing them. Here is foo.js (note that my use case has a lot more input arguments):

export function foo(arg1, arg2) {
  doStuff()
}

Here is my code; the following works :

import { foo } from 'foo'

const args = {
  arg1: "value1",
  arg2: "value2",
}

const { arg1, arg2 } = args
foo(arg1, arg2)

I would like to be a bit more concise and avoid repeating the variable names arg1 and arg2, along the lines of:

import { foo } from 'foo'

const args = {
  arg1: "value1",
  arg2: "value2",
}

foo(args) // doesn't work, apparently I have to do something more to the args object here

But this code doesn't work (arg1 gets the value of args and arg2 is undefined), I assume that this can be achieved, e.g. using the spread operator somehow, but how?

4
  • 3
    function bar({ arg1, arg2 }), see MDN Commented Jan 10, 2020 at 14:53
  • you need to get the properties before you call the function unless you change the singature of the function to accept an object for destructuring. Commented Jan 10, 2020 at 14:55
  • @ASDFGerte I don't have access to the declaration of foo/bar, I updated the question to reflect this Commented Jan 10, 2020 at 15:00
  • 1
    Then either use your own suggestion of just calling it by listing the properties as parameters, or write a wrapper, and use that instead (just make a new function function fooWrapped({ arg1, arg2 }){ return foo.call(this, arg1, arg2); }) Commented Jan 10, 2020 at 15:05

3 Answers 3

3

destructure the object in the function declaration like so:

function({arg1 = "", arg2 = 0}) {doStuff()}

and remember to always add default values :)

EDIT: what you're doing is impossible basically, because you can't use iterators like this foo(..{arg1, arg2). A solution to this would be unwrapping the object values using Object.values converting them into an array and then destructuring that.

function foo(arg1, arg2) {
  console.log(arg1, arg2);
}

function unwrap(object) {
  return Object.values(object);
}

foo(...unwrap({ x: "1", y: "2" }));

at this point tho you'd be better off using an array like so:

foo(...[1, 2]);
Sign up to request clarification or add additional context in comments.

2 Comments

I do not actually have access to the function declaration. Let me update the question to clarify this
Ah then you have to wrap it, I'll update my answer accordingly :)
0

You could take a function for unwrapping the arguments object and spread the result for calling the wanted function without changing the function's signature.

// given function
function foo(arg1, arg2) {
    console.log(arg1, arg2);
}

const
    unwrap = ({ arg1, arg2 }) => [arg1, arg2], // get all properties in wanted order
    args = { arg1: "value1", arg2: "value2" };

foo(...unwrap(args));

2 Comments

Ok, this looks like it would work but seems similarly or more complex than my first suggestion (destructuring first). I would like to reduce the number of times that I type arg1, arg2 etc. to 1.
objects have no order. if you are sure about the order, you could take o => Object.values(o);
0

Use Map instead object to save insertion order:

const args = new Map();

args.set('arg1', 'value1');
args.set('arg2', 'value2');

foo(...args.values());

Comments

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.