So I need to make make a callback in one of my functions, but due to the way the whole program is working, I need to pass the callback function name in the form of a string rather than the function itself.
For example:
function doThings(callback){
alert('hello');
eval(callback + '();');
}
function test(){
alert('world!');
}
var func = 'test';
doThings(func);
In short, I'm trying to dynamically change which function is used, and I have to use a string to represent the callback function rather than an actual function reference.
I keep reading eval is evil - is there any way to do this without eval()
?
EDIT: I do not have the ability to list out the functions in an object beforehand. I also need to pass an array as individual arguments to this function, and for some reason .apply()
doesn't get along well with window[callback]()
So I need to make make a callback in one of my functions, but due to the way the whole program is working, I need to pass the callback function name in the form of a string rather than the function itself.
For example:
function doThings(callback){
alert('hello');
eval(callback + '();');
}
function test(){
alert('world!');
}
var func = 'test';
doThings(func);
In short, I'm trying to dynamically change which function is used, and I have to use a string to represent the callback function rather than an actual function reference.
I keep reading eval is evil - is there any way to do this without eval()
?
EDIT: I do not have the ability to list out the functions in an object beforehand. I also need to pass an array as individual arguments to this function, and for some reason .apply()
doesn't get along well with window[callback]()
- Which environment are you in? In a browser you might do doThings(window[func]), window['test']() etc., so you can access the function by name from the parent scope object. – DevDig Commented Nov 2, 2016 at 10:14
- @DevDig It's in browser. I tried that, but doing window[func]().apply(null, args) doesn't work. I should have mentioned that earlier. I need to also pass an array as individual arguments to the function. With that said, is it necessarily insecure to use eval() if I'm limiting all of the variables in it to being alphanumeric? How is this less secure than say generating SQL and sanitizing inputs? – geekman Commented Nov 2, 2016 at 10:39
- window[func]() should do the trick as well as window[func].apply(null, args). Some informations about evil eval: javascriptweblog.wordpress.com/2010/04/19/how-evil-is-eval – DevDig Commented Nov 2, 2016 at 11:01
3 Answers
Reset to default 10You can do this, in this way.
function doThings(callback){
alert('hello');
window[callback]();
}
function test(){
alert('world!');
}
var func = 'test';
doThings(func);
Or you can pass the full function in string and use the Function
constructor.
function doThings(callback){
alert('hello');
(new Function('return '+callback)())();
}
function test(){
alert('world!');
}
var func = test.toString();
doThings(func);
Store the functions in an object. Use the property names to access them.
function doThings(callback) {
alert('hello');
my_possible_functions[callback]();
}
function test() {
alert('world!');
}
var my_possible_functions = {};
my_possible_functions.test = test;
var func = 'test';
doThings(func);
A very similar answer to @Quentin's but with additional checks
- Check if its a part of current Object
- Check if value is of type
function
. If value is not a function, it will break your code.
function doThings(callback) {
console.log('hello ', callback);
try {
callbackList[callback]()
} catch (ex) {
console.log(ex.message)
}
callbackList.hasOwnProperty(callback) && typeof(callbackList[callback]) === 'function' && callbackList[callback]()
}
Object.prototype.test3 = function() {
console.log("this should not be called");
}
var callbackList = {
test: function test() {
console.log('world!');
},
test2: "World"
}
doThings('test');
doThings("test2");
doThings("test3");