geekman
geekman

Reputation: 123

Javascript: Is there a way to use a string as a callback without eval()?

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]()

Upvotes: 8

Views: 8112

Answers (3)

Quentin
Quentin

Reputation: 944203

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);

Upvotes: 8

Steeve Pitis
Steeve Pitis

Reputation: 4443

You 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);

Upvotes: 10

Rajesh
Rajesh

Reputation: 24945

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");

Upvotes: 0

Related Questions