This blog post examines how one can dynamically evaluate code in JavaScript.
eval(str)evaluates the JavaScript code in str. For example:
> var a = 12; > eval('a + 5') 17Note that eval() parses in statement context [1]:
> eval('{ foo: 123 }') // code block 123 > eval('({ foo: 123 })') // object literal { foo: 123 }
function f() { eval('var foo = 1'); console.log(foo); // 1 }That isn’t possible in strict mode. However, evaluated code still has read and write access to variables in surrounding scopes. To prevent such access, you need to call eval() indirectly.
var x = 'global'; function directEval() { 'use strict'; var x = 'local'; console.log(eval('x')); // local }Conversely, indirect eval() executes it in global scope.
var x = 'global'; function indirectEval() { 'use strict'; var x = 'local'; // Call eval in a different way console.log(eval.call(null, 'x')); // global console.log(window.eval('x')); // global console.log((1, eval)('x')); // global (1) // Store eval somewhere else var xeval = eval; console.log(xeval('x')); // global var obj = { eval: eval }; console.log(obj.eval('x')); // global }Explanation of (1): When you refer to a variable via its name, the initial result is a so-called reference, a data structure with two main fields:
Indirectly evaluated code is always sloppy. That is a consequence of the code being evaluated independently of its current surroundings.
function strictFunc() { 'use strict'; var code = '(function () { return this }())'; var result = eval.call(null, code); console.log(result !== undefined); // true, sloppy mode }
new Function(param1, ..., paramN, funcBody)It creates a function whose zero or more parameters have the names param1 etc. and whose body is funcBody. That is, the created function looks like this:
function («param1», ..., «paramN») { «funcBody» }Example:
> var f = new Function('x', 'y', 'return x+y'); > f(3, 4) 7Similar to indirect eval(), new Function() creates functions whose scope is global.
var x = 'global'; function strictFunc() { 'use strict'; var x = 'local'; var f = new Function('return x'); console.log(f()); // global }Such functions are sloppy by default.
function strictFunc() { 'use strict'; var sl = new Function('return this'); console.log(sl() !== undefined); // true, sloppy mode var st = new Function('"use strict"; return this'); console.log(st() === undefined); // true, strict mode }
var value = eval('obj.'+propName);The following code is better:
var value = obj[propName];You also shouldn’t use eval() or new Function() to parse JSON data. That is unsafe. Either rely on ECMAScript 5’s built-in support for JSON [3] or use a library.
Legitimate use cases. There are a few legitimate, albeit advanced, use cases for eval() and new Function(): configuration data with functions (which JSON does not allow), template libraries, interpreters, command lines and module systems.
Acknowledgement. Mariusz Nowak (@medikoo) told me that code evaluated by Function is sloppy by default, everywhere.