Hey, in today's blog, we are going to briefly discuss eval()
and Function()
in JavaScript.
Let us begin.
Brief
eval()
and Function()
are two powerful tools in JavaScript that both allow you to evaluate any JavaScript expression passed to either of them as a string. They are both used for the same thing, though they differ in how they handle your expression.
Let us begin with eval()
.
eval()
eval()
is a global function which takes a JavaScript expression as a string and executes it. It does not return anything except undefined
. If you write some script into your HTML and use eval()
, you will notice the output gets printed to the console while in an environment like node, you will want to use console.log()
. This is because it tend to pipe the result of an expression for example to standard output or an equivalent.
Let us have an example. Say you write an app where a user inputs some value and your app has to output the result to the console. Tricky right? eval()
saves you time. Just pass what the user inputs to eval and let the magic.
let userInput = "2+4";
eval(userInput); // output : 6
Function()
An alternative to eval is Function()
. Just like eval(), it takes some expression as a string for execution except rather than outputing the result directly, it returns to you an anonymous function which you can call. It is a faster and more secure alternative to eval(). Let us try the same example as above but with Function()
.
let userInput = "2+4";
let result = Function(userInput);
If you try to log the result of above, you will get
function anonymous() {
2+4
}
Why so ? This is because Function()
returns to us an anonymous function. Looking more, we can see that the expression we passed in the string is found in the function body.
What if we add a return statement in our string ?
let userInput = "2+4";
let result = Function("return " + userInput); // which is same as "return 2+4"
Try logging result once more. We get this
function anonymous() {
return 2+4
}
We notice we are now returning the result of our arithmetic operation. But now we want the actual value. We can get this by executing the function.
let userInput = "2+4";
let result = Function("return " + userInput)(); // which is same as "return 2+4"
Now if you log result and look up the console, you will notice we get 6, which is the result we expect.
Note
With great power comes great responsibility
eval()
and Function()
are really powerful tools we have at hand in JavaScript. But that power comes at a price. Arbitrary code can be executed by a technical enough user or malicious individual.
eval()
is particularly dangerous. This is because it allows one to execute code with the same privileges as the caller of eval()
. Say you create an app that evalues some code and stores the result on the user's machine using the FileApi in the browser. The user can use eval()
against your app and get access to FileAPI too to carry out malicious tasks.
Again, eval()
is much slower than Function()
.
Quote here
eval() is also slower than the alternatives, since it has to invoke the JavaScript interpreter, while many other constructs are optimized by modern JS engines.
Additionally, modern javascript interpreters convert javascript to machine code. This means that any concept of variable naming gets obliterated. Thus, any use of eval() will force the browser to do long expensive variable name lookups to figure out where the variable exists in the machine code and set its value. Additionally, new things can be introduced to that variable through eval() such as changing the type of that variable, forcing the browser to re-evaluate all of the generated machine code to compensate.
Learn more about eval and Function
Prefer Video ?
Top comments (5)
Really glad you acknowledge some of the risks of using
eval
andFunction
.Though if you're using
eval
for user-inputted code, I would recommend against it. I think there are safer alternatives if it's absolutely needed, or other solutions that do not require the use ofeval
.what would be an alternative for lets say if am building a calculator and i want to parse the user input
It depends on the scope of the calculator, if it's a simple one you could implement it yourself, it's quite simple actually. If the calculator is a bit more complex you could use some expression library, like github.com/silentmatt/expr-eval or mathjs.org/. Either way, I recommend checking if they have any security considerations.
Take into account, that you might not need to worry about security as much on a simple calculator, as on a more serious or sensitive application (has user's info, banking details, passwords, etc...). You might be ok using eval in this scenario.
This is something you have to evaluate yourself, is your app/project sensitive? can a malicious actor take advantage of it and harm or access hidden information? etc...
Great article ! what did you mean when you say "variable naming gets obliterated" 😅 wasn't able to get it
The variable names become indistinct from the one you create in eval() which may result into conflicts