JavaScript for impatient programmers (ES2021 edition)
Please support this book: buy it or donate
(Ad, please don’t block.)

26 Evaluating code dynamically: eval(), new Function() (advanced)



In this chapter, we’ll look at two ways of evaluating code dynamically: eval() and new Function().

26.1 eval()

Given a string str with JavaScript code, eval(str) evaluates that code and returns the result:

> eval('2 ** 4')
16

There are two ways of invoking eval():

“Not via a function call” means “anything that looks different than eval(···)”:

The following code illustrates the difference:

globalThis.myVariable = 'global';
function func() {
  const myVariable = 'local';
  
  // Direct eval
  assert.equal(eval('myVariable'), 'local');
  
  // Indirect eval
  assert.equal(eval.call(undefined, 'myVariable'), 'global');
}

Evaluating code in global context is safer because the code has access to fewer internals.

26.2 new Function()

new Function() creates a function object and is invoked as follows:

const func = new Function('«param_1»', ···, '«param_n»', '«func_body»');

The previous statement is equivalent to the next statement. Note that «param_1», etc., are not inside string literals, anymore.

const func = function («param_1», ···, «param_n») {
  «func_body»
};

In the next example, we create the same function twice, first via new Function(), then via a function expression:

const times1 = new Function('a', 'b', 'return a * b');
const times2 = function (a, b) { return a * b };

  new Function() creates non-strict mode functions

By default, functions created via new Function() are sloppy. If we want the function body to be in strict mode, we have to switch it on manually.

26.3 Recommendations

Avoid dynamic evaluation of code as much as you can:

Very often, JavaScript is dynamic enough so that you don’t need eval() or similar. In the following example, what we are doing with eval() (line A) can be achieved just as well without it (line B).

const obj = {a: 1, b: 2};
const propKey = 'b';

assert.equal(eval('obj.' + propKey), 2); // (A)
assert.equal(obj[propKey], 2); // (B)

If you have to dynamically evaluate code: