0

I'm looking for a way to transform a list of function arguments to a single object, where each argument results in a property on the object with the appropriate name.

Basically, what I want to achieve is something such as:

const foo = function (a, b, c) {
  const args = getObjectFromArguments(a, b, c);
  // or: getObjectFromArguments(arguments);
  // or: getObjectFromArguments();

  console.log(args);
  // { a: 2, b: 3, c: 4 }
};

foo(2, 3, 4);

How can I do this without the need to provide the arguments' names as reference and as a string, ideally even without using more complex constructs? The call to getObjectFromArguments should be as simple as possible.

Any ideas?

Golo Roden
  • 140,679
  • 96
  • 298
  • 425
  • 2
    Ehm, [arguments object](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/arguments) is not enough? – Sergio Tulentsev Aug 03 '16 at 07:23
  • 1
    You cannot do that, because variable names are not guaranteed to be available in run time. – zerkms Aug 03 '16 at 07:24
  • How about `getObjectFromArguments(arguments)`, grab the `arguments` which looks like an array but not actually an array. However you can loop them over. But names would be an issue because they could be anything. – Rohit416 Aug 03 '16 at 07:26
  • 1
    @GoloRoden, can you please tell us your objective? Zoom out. Don't ask about this bit of code you've written. Ask us how to accomplish your actual goal. – Mulan Aug 03 '16 at 07:27
  • 1
    My take on this is that a function is superfluous for this. [The functionality you are looking for is part of the ES6 syntax](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Object_initializer). You just need to write `{ a, b, c }` (with any arguments you want) instead of `uselessFunction(a, b, c)`. – Quentin Roy Aug 03 '16 at 08:09
  • @Roque If you turn your comment into an answer, I will accept this. Thanks for the (great) idea :-) … okay, just seen that you did, and that it was massively downvoted. I voted to undelete it, and if it gets undeleted, I will accept it. – Golo Roden Aug 03 '16 at 10:48
  • It was, but everybody thought it was not what you wanted so I removed it. I just undeleted it. – Quentin Roy Aug 03 '16 at 11:11

3 Answers3

2

It is not possible.

Not only the variable names are not generally available in run time, but they also might be changed (mangled) during minification (or any other transformation) process.

Also, the variable values are evaluated before values are passed as a function parameters. That makes existence of a general purpose function (like you named it getObjectFromArguments) even less possible.

From the other hand - the whole idea smells and might be a sign that you're doing something in a terribly weird way (but there might be exceptions from that indeed).

zerkms
  • 249,484
  • 69
  • 436
  • 539
1

A function is superfluous for this. The functionality you are looking for is already part of the ES6 syntax as a shorthand notation for object initialisation. You just need to write { a, b, c } instead of uselessFunction(a, b, c).

const foo = function (a, b, c) {
  const args = { a, b, c };
  console.log(args);
};

foo(2, 3, 4);

However, it is not possible using "only" the arguments object (your second example), and even less with a function that doesn't take any arguments (your last example). If you are looking for something like python's keyword arguments, it is not currently possible in JavaScript except by accepting only a single object as argument.

Community
  • 1
  • 1
Quentin Roy
  • 7,677
  • 2
  • 32
  • 50
  • "How can I do this without the need to provide the arguments' names as reference" – zerkms Aug 03 '16 at 07:24
  • @werkms I think it complies. The arguments' names are not provided as references. How I understand it, OP doesn't want to have an argument with an array of string containing the name of the properties of the resulting object. – Quentin Roy Aug 03 '16 at 07:25
  • 1
    You provided them as `a, b, c` identifiers. – zerkms Aug 03 '16 at 07:26
  • This is not an argument. – Quentin Roy Aug 03 '16 at 07:27
  • 1
    The OP's aim is to have a general purpose function named `getObjectFromArguments` that can accept any number of arguments and that would infer the parameter names in runtime. – zerkms Aug 03 '16 at 07:28
  • Well my point is that you do not need a function for this. It is already part of the language. – Quentin Roy Aug 03 '16 at 07:32
  • Your point does not correlate with the question asked. I don't say your point or your code is syntactically wrong, it just does not address the initial question. – zerkms Aug 03 '16 at 07:33
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/118980/discussion-between-roque-and-zerkms). – Quentin Roy Aug 03 '16 at 07:49
1

var foo = function(x,y,z) {
  console.log(getFnParamNames(arguments));
};

function getFnParamNames(args){
  var names =  args.callee.toString().match(/\(.*?\)/)[0].replace(/[()]/gi,'').replace(/\s/gi,'').split(','),
      result = {};
  for (var i in names) {
    result[names[i]] = args[i];
  }
  return result;
}

foo(2,3,4);

However, as this solution makes use of arguments.callee that is forbidden starting from ES5 in strict mode, it won't work in this case.

Quentin Roy
  • 7,677
  • 2
  • 32
  • 50
pyda
  • 11
  • 2
  • It needs a note that it's not a standard JS (hence is not guaranteed to work). – zerkms Aug 03 '16 at 08:17
  • Good point. You should read https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments/callee – pyda Aug 03 '16 at 08:46