eval()
, new Function()
(advanced)In this chapter, we’ll look at two ways of evaluating code dynamically: eval()
and new Function()
.
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(···)
”:
eval.call(undefined, '···')
(uses method .call()
of functions)
eval?.()
() (uses optional chaining)
(0, eval)('···')
(uses the comma operator)
globalThis.eval('···')
const e = eval; e('···')
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.
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.
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:
new Function()
over eval()
: it always executes its code in global context and a function provides a clean interface to the evaluated code.
eval
over direct eval
: evaluating code in global context is safer.