Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the best way to replace eval?

Tags:

javascript

I deal with a JavaScript code to improve. The idea here is to invoke functions dynamically.

Here is the code to replace:

//this.actionCallback return the name of the function to invoke
eval(this.actionCallback + "('testArgument')");

What is the best way to replace it:

This way:

window[this.actionCallback]("testArgument");

Or this way:

var actionToCall = this.actionCallback+'("testArgument");';
var functionToInvoke = new Function(actionToCall);
functionToInvoke();

Or is there is a better way to do this?

like image 459
chewb Avatar asked May 13 '11 14:05

chewb


People also ask

Is it bad to use eval?

eval() Warning: Executing JavaScript from a string is an enormous security risk. It is far too easy for a bad actor to run arbitrary code when you use eval() .

What is eval method?

The Eval function evaluates the string expression and returns its value. For example, Eval("1 + 1") returns 2. If you pass to the Eval function a string that contains the name of a function, the Eval function returns the return value of the function.

Why is eval slow?

Calling eval() will be slower than using alternatives, because it has to call JavaScript interpreter, which will convert evaluated code to the machine language. That means if you run the code more than once, the browser will have to interpret the same code again, which is highly inefficient.


2 Answers

The first way is a much better method - new Function(actionToCall) is just eval in disguise.

like image 173
Jamie Wong Avatar answered Sep 29 '22 20:09

Jamie Wong


Both of the alternatives you have mentioned are not equivalent to the first one:

  • Your first alternative requires that the function name be the member of window (in other words, defined at global scope). Having a function inside another scope will cause this to fail, but it doesn't use eval. :)

  • Your second alternative creates a function object using the Function() constructor, so this also only works when the function in declared at the global scope, because a function defined by a Function constructor does not inherit any scope other than the global scope, and as said in Jamie Wong's answer, using the Function() constructor is still considered as eval :(

Here is an alternative that should work like your first one, but looks slightly better, but still uses eval.

eval(this.actionCallback)("testArgument");

But the best way is that this.actionCallback should be a real function object, and not just a function's name, then you can call:

this.actionCallback("testArgument");
like image 40
Thai Avatar answered Sep 29 '22 20:09

Thai