As MDN says on eval
:
var
-declared variables and function declarations would go into the surrounding scope if the source string is not interpreted in strict mode — for indirect eval, they become global variables. If it's a direct eval in a strict mode context, or if the eval
source string itself is in strict mode, then var
and function declarations do not "leak" into the surrounding scope.
Here, you're using direct eval (because you're referencing eval
) directly, and that "surrounding scope" is the inside of the click handler. To see this working, click, then see how the function f
approach defines an f
referenceable later in the click handler (but not outside of it):
document.getElementById('button1').onclick = () => {
eval("function f() { alert('hello'); }");
f();
}
// scope doesn't extend to out here
setTimeout(() => console.log(typeof f), 3000);
<div id="button1">1 Click me to define f as a function</div>
Doing
f = () => { ... };
is just like doing that in plain code, without eval
- without declaring it with const
, let
, var
, or function
, you're implicitly assigning to the global object, so
eval("f = () => { alert('hello'); };");
is equivalent to
eval("window.f = () => { alert('hello'); };");
if no f
variable exists in scope at that time.
// runs
(() => {
f = () => console.log('f');
})();
f();
// doesn't run
(() => {
function g() {
console.log('g');
}
})();
g();
Inline handlers may only reference global variables (99% of the time), so for onclick="f();"
to work, window.f
must exist.
You're using direct eval. Note that if you used indirect eval, the evaled code won't run in the scope of where the eval
reference was called, but rather on the top level - and as a result, any variable declaration inside such an eval will be visible everywhere.
// both work
const indirectEval = eval;
document.getElementById('button1').onclick = () => indirectEval("function f() { alert('hello'); }");
document.getElementById('button2').onclick = () => indirectEval("f = () => { alert('hello'); };");
<div id="button1">1 Click me to define f as a function</div>
<div id="button2">2 Click me to define f as a variable function</div>
<div id="button3" onclick="f();">3 Click to run f()</div>