7

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?

6
  • 5
    the better question is why are you using eval? eval does magical things. it is best to leave it alone. Commented Sep 17, 2016 at 20:08
  • 1
    Sometimes for remote testing I need to quickly load and run my local code. Not for production code :) Commented Sep 17, 2016 at 20:11
  • stackoverflow.com/a/17281213/1005215 Commented Sep 17, 2016 at 20:12
  • @NehalJWani it's not related, question is about capturing when you use eval. Thanks. Commented Sep 17, 2016 at 20:15
  • 1
    "Sometimes for remote testing I need to quickly load and run my local code" - then I recommend you find a better way to do that. You have problems understanding what is going on now already, so it is likely that you come across such or similar behavior again when testing this way - so you will never be able to quickly determine whether a problem is with your actual code, or just with the way you are getting it to execute. I'd rather use debugging tools that make my life easier, not harder. Commented Sep 17, 2016 at 20:40

4 Answers 4

7

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

Sign up to request clarification or add additional context in comments.

Comments

3

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.

Comments

2

You can use Function.prototype.bind() to pass x to returned function

var f = function () {
    var x = 10;

    function y(n) {
        eval(`console.log(${n})`);
        window["eval"](`console.log(${n})`);
    }

    return y.bind(this, x)
};

f()();

1 Comment

Well, this is string interpolation, you don't even need bind for this, you could just interpolate the variable directly in the eval statement without using a parameter. f = function() { var x = 5; return function () { eval(`console.log(${x})`) } }
1

window.eval work in global scope.

var variable = 1;

(function(){
  var variable = 100,
      cmd = "++variable";
  document.write(eval(cmd)+"\n"); // increment local var 100 and output 101
  document.write(window.eval(cmd)+"\n"); // increment global var 1 and output 2
})();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.