I faced with strange behaviour when using eval
in JS.
var f = function () {
var x = 10;
return function () {
eval('console.log(x);');
window['eval']('console.log(x);');
}
};
f()();
OUTPUT:
10
undefined:1
console.log(x);
^
ReferenceError: x is not defined
Why using eval
explicitly captures the x
but global['eval']
doesn't?
And even though global['eval']
doesn't capture x
, why it's unable to see after eval
, which already captured x
?
A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function's scope from an inner function.
JavaScript Hoisting refers to the process whereby the interpreter appears to move the declaration of functions, variables or classes to the top of their scope, prior to execution of the code.
window['eval'] operates at global scope, eval() operates at local scope.
From Mozilla's Javascript reference:
If you use the eval function indirectly, by invoking it via a reference other than eval, as of ECMAScript 5 it works at global scope rather than local scope; this means, for instance, that function declarations create global functions, and that the code being evaluated doesn't have access to local variables within the scope where it's being called.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval
Your inner function does not actually capture the reference of x
, and so it is never directly passed to eval
.
eval
usually works at the local scope and so the first call succeeds (because the local scope contains the declaration of x).
However, if you invoke eval in such a way that you don't have a direct reference to it, it will invoke itself in the global scope, which var x
is not a part of, and it fails.
Just don't use eval.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With