driima
driima

Reputation: 643

Call JavaScript Function using object values as parameters

I have an object:

var obj = {
    foo: 'foo',
    bar: 'bar'
};

And I have a function:

var f = function(bar, foo) {
    // Do something with bar and foo
};

Is there a way I can dynamically call the function using the object, so that obj['foo'] is passed as the 'foo' parameter, and obj['bar'] is passed as the 'bar' parameter? Note that I may not know the actual names of the keys and values or the function argument names, the ones provided are just an example, so f.call(this, obj['bar'], obj['foo']); won't do.

Upvotes: 0

Views: 1892

Answers (5)

Caojs
Caojs

Reputation: 185

You can write a function which will wrap your function and use new function instead to get what you want.

function wrapper(fn) {
  var fnString = fn.toString();
  var fnRegex = /\((.*)\)/;

  var params = fnString
    .match(fnRegex)[1]
    .replace(/\s/, '')
    .split(',')
    .filter(function(arg) {
      return arg;
    });

  return function (o) {
    var args = params
      .map(function(arg) {
        return o[arg];
      });
    return fn.apply(null, args);
  }
}

// Example: your function.
function yourFunc(foo, bar) {
  console.log('my foo: ' + foo);
  console.log('my bar: ' + bar);
}

// wrap your function and use new function instead.
var enhancedFunc = wrapper(yourFunc);

enhancedFunc({foo: 1, bar: 2});

Upvotes: 0

driima
driima

Reputation: 643

Based on deceze's comment, I managed to come up with a solution. I'm not exactly sure how fast it is, but it gets the job done. Improvements are welcome! Thanks for everyone's help.

I used this function from this answer:

function getParameterNames(fn){
    var fstr = fn.toString();
    return fstr.match(/\(.*?\)/)[0].replace(/[()]/gi,'').replace(/\s/gi,'').split(',');
}

And made the following:

var obj = {
    foo: 'foo',
    bar: 'bar'
};

var f = function(bar, foo) {
    // Do something with bar and foo
};

var sortedArgs = [];
getParameterNames(f).forEach(function(item) {
    sortedArgs.push(args[item]);
});

f.apply(this, sortedArgs);

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386578

You could bind the object to the function.

The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.

var obj = {
        foo: 'foo',
        bar: 'bar'
    },
    f = function(k) {
        console.log(this[k]);
    }.bind(obj);

f('foo');

Upvotes: 0

Nenad Vracar
Nenad Vracar

Reputation: 122047

You could check if provided argument is object and then use destructuring

var obj = {
  foo: 'foo',
  bar: 'bar'
};

var f = function(foo, bar) {
  if(typeof arguments[0] == 'object') var {foo, bar} = arguments[0];
  console.log('Foo: ' + foo);
  console.log('Bar: ' + bar)
};

f(obj);
f('lorem', 'ipsum');

Upvotes: 0

georg
georg

Reputation: 214959

Sure, in ES6

var f = function({bar, foo}) {
    console.log('foo', foo, 'bar', bar)
};

var obj = {
    foo: '11',
    bar: '22'
};


f(obj)

Upvotes: 2

Related Questions