Reputation: 643
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
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
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
Reputation: 386578
You could bind the object to the function.
The
bind()
method creates a new function that, when called, has itsthis
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
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
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