Everything Frontend

Different ways to evaluate string as code in JavaScript

Dynamic code evaluation is a very controversial subject in every programming language that allows it, but especially in javascript since it can be a major security risk, especially when evaluating code from untrusted source. Nevertheless it is useful technique, that can be helpful in development scenarios or in certain edge cases as an optimization tool e.g. for dynamic loop unwinding.

Let’s look look at the ways we can evaluate string as a javascript code.

eval()

The eval function in it’s default form looks like this:

eval("alert('lorem ipsum')");

This will parse and execute code provided as a string in current context. It even allows you to define variables within current scope which leads to many performance and security problems. This will still show text “lorem ipsum” in an alert popup:

eval("var text = 'lorem ipsum';");
alert(text);

You can read more about eval and it’s behavior on MDN. You should also take a look at eval differences when running in strict mode.

setTimeout()

If you want to run some cody asynchronously you can pass a string as a first parameter to setTimeout and it will get evaluated after a timeout in a global context.

setTimeout("alert('lorem ipsum')", 100);

This is pretty much equivalent to

setTimeout(function(){ eval("alert('lorem ipsum')"); }, 100);

new Function()

Function constructor provides a way to specify function parameters and body as strings. Following code will alert “8”:

var adder = new Function("a", "b", "return a + b");
alert(adder(3,5));

Dynamically created function are executed in global context unless it running in sctrict mode, in which case context is undefined. It can be demosntrated by this code, which would alert “undefined”:

alert((new Function("'use strict'; return typeof this;"))());

document.write()

Since any value passed to document.write gets appended to the current html document, parsed and evaluated (if needed) we can use it to execute some javascript code like so:

var script = 'script>';
document.write('<' + script + 'alert("lorem ipsum")</' + script)

Since it’s the same as if the code was included in the HTML right way the context of execution is global object.

Data URI

While this method is not as well known as all previously mentioned it does work pretty well and even has some advantages when it comes to debugging. So here’s what it looks like:

var s = document.createElement('script');
s.src = 'data:text/javascript,' + encodeURIComponent('alert("lorem ipsum")')
document.body.appendChild(s);

Since this is exactly the same as if we loaded javascript file from the server it gets treated as a separate file allowing for better debugging with breakpoints and all the other bells and whistles provided by Chrome Web Inspector which is nice.

There is a slight issue with browser support though — IE7 doesn’t support data URI and IE8 is limited to 32kb.