Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript variable capture

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?

like image 783
Sergey Sahakyan Avatar asked Sep 17 '16 20:09

Sergey Sahakyan


People also ask

What is a closure function in JavaScript?

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.

What is variable hoisting in JS?

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.


2 Answers

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

like image 187
StvnBrkdll Avatar answered Nov 05 '22 12:11

StvnBrkdll


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.

like image 21
Dan Avatar answered Nov 05 '22 10:11

Dan