0

I have a string that is my javaScript function:

var foo = "CONCATENATE('a', ' ', 'b')";

How to make javaScript call of this function without using eval()?

Walery Strauch
  • 6,792
  • 8
  • 50
  • 57
  • 5
    This is much what `eval` is for… and a rose by any other name……… I'd try to refactor to avoid putting all that data in a string in the first place. – Quentin Jun 03 '13 at 11:10
  • 3
    I would look at why you are needing to do this, and consider a redesign. As Quentin says, as evil as eval is, this is it's exact purpose. Just ensure that string isn't coming from a user input. – MasNotsram Jun 03 '13 at 11:12
  • 1
    You can build a "whitelist" of possible functions and parse the string yourself. Lots of work and reinventing the wheel but it would work. – Shadow The GPT Wizard Jun 03 '13 at 11:15
  • In javascript there is no way to use strings as code without eval(); – Givi Jun 03 '13 at 11:16

2 Answers2

2

:) This is an interesting question. Let me go through this one step at a time. This will not be able to handle everything, but just functions with string parameters.

Here's a jsFiddle with some basic code: http://jsfiddle.net/Sqa8L/

Note that I haven't tested it at all, so use with utmost care.

Step 1: Use a regex to get the function name

Ideally, I'd recommend using a parser of some sort to get much more reliable results, but I think you can follow through on this answer once you've understood the general concept. So, the regex first:

var matchFnName = /^([^(]+)\(([^)]+)\)/.exec(str);

This would give you two matches, one for the function name, and the second with the entire parameter list. (unless you have complex expressions in there, in which case, it will fail :) ).

Extract arguments

I've just split using the simple statement:

var paramList = paramListStr.split(',');

This will fail if any strings contain a ','. You will need a better parsing technique to handle this.

Call the function on an object

You would need to send an object that would respond to the function call, or it defaults to the global scope.

onObject[fnName].apply(onObject, paramList);

Look at apply here. Basically, what apply does is call the function on the object supplied in the first argument onObject, with an argument list passed in the second argument paramList.

Hope this helps to get you started in the general direction.

Mutahhir
  • 3,812
  • 3
  • 21
  • 26
1

Whichever solution you will use, it will either implicitly or explicitly call eval() at javascript level or it's equivalent at the engine level.

ElmoVanKielmo
  • 10,907
  • 2
  • 32
  • 46
  • Why a downvote? Maybe I didn't make myself clear - `eval()` is a builtin function, which executes it's string argument as source code. If you can show me a more robust or safe way to execute a string in javascript, I would accept this downwote. No developer should "reinvent the wheel", if there is nothing to gain. – ElmoVanKielmo Jun 03 '13 at 11:23