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 can’t happen 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 also 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 }
Often, there are better alternatives. For example, Brendan Eich recently tweeted an anti-pattern used by programmers who wanted to access a property whose name was stored in a variable propName:
var value = eval('obj.'+propName);The idea makes sense: The dot operator only supports fixed, statically provided property keys. But in this case, the property key is only known at runtime, which is why eval() is needed in order to use that operator. Luckily, JavaScript also has the bracket operator, which does accept dynamic property keys. Therefore, the following is a better version of the above code:
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.