44

Is it possible to use the eval command to execute something with a global scope? For example, this will cause an error:

<script>
 function execute(x){
 eval(x);
 }

 function start(){
  execute("var ary = new Array()");
  execute("ary.push('test');");  // This will cause exception: ary is not defined
 }

</script>
<html><body onLoad="start()"></body></html>

I know the 'with' keyword will set a specific scope, but is there a keyword for the global scope? Or is it possible to define a custom scope that would allow this to work?

<script>

 var scope = {};
 function execute(x){
  with(scope){
   eval(x);
  }
 }

 function start(){
  execute("var ary = new Array()");
  execute("ary.push('test');");  // This will cause exception: ary is not defined
 }

</script>
<html><body onLoad="start()"></body></html>

Essentially, what I am trying to do is have a global execute funciton...

wuntee
  • 12,170
  • 26
  • 77
  • 106

6 Answers6

43
(function(){
    eval.apply(this, arguments);
}(a,b,c))

This will invoke eval using the global object, window in browsers, as the this argument passing any arguments you've passed into the anonymous function.

eval.call(window, x, y, z) or eval.apply(window, arguments) is also valid if you're certain window is the global object. This isn't always true, however. For instance, the global object in a Node.js script is process if I remember correctly.

Lucas Willems
  • 6,673
  • 4
  • 28
  • 45
orca
  • 717
  • 6
  • 12
  • 3
    `eval.call(windwow,x); ` worked for me, cross-browser implementation. reason is, the global scope should always be the `window` object and subsequently defined functions will pertain to this object, as in `JSON.stringify` for example is nothing more than `window['JSON']['stringify']` and event `window['window']['window']['window']['window']['JSON']['stringify']`; both will still work. – Silviu-Marian Apr 12 '12 at 11:44
  • This really helps! I had "Date" being set locally by the function calling me and I wanted the global version of the Date object which is window.Date. – Curtis Yallop Oct 22 '12 at 16:19
  • 4
    -1. Read http://perfectionkills.com/global-eval-what-are-the-options/ on what really happens. – Bergi Aug 09 '14 at 14:37
10

Use (1, eval)('...').

$ node
> fooMaker = function () { (1, eval)('foo = "bar"'); };
[Function]
> typeof foo
'undefined'
> fooMaker()
undefined
> typeof foo
'string'
> foo
'bar'
pyrospade
  • 7,870
  • 4
  • 36
  • 52
  • 5
    I'm not sure what kind of black magic is this, but it works amaizingly fine. I would love to understand what the heck is going on here, could you please explain? :) – Gonzalo Larralde May 05 '17 at 00:48
  • 1
    @GonzaloLarralde : See https://stackoverflow.com/questions/9107240/1-evalthis-vs-evalthis-in-javascript – Brett Zamir Jul 09 '18 at 21:25
6

You should be able to use eval() in global scope by calling it indirectly. However, not all browsers are currently doing this.

Further Reading.

alex
  • 479,566
  • 201
  • 878
  • 984
3

To execute some JavaScript in the global scope you can call it indirectly by using setTimeout() or if you are using jQuery, take a look at $.globalEval().

Changing your execute method to the following will allow you to still use the 'var' keyword:

function execute(x) {
    setTimeout("eval(" + x + ")", 0);
    // Or: $.globalEval(x);
}


function start() {
    try
    {
        execute("var ary = new Array()");
        execute("ary.push('test');");
    }
    catch (e)
    {
        alert(e);
    }
}


start();
Ed .
  • 6,373
  • 8
  • 62
  • 82
1

Use eval.apply(null, ["code"]);.

eval.apply(this, ["code"]); does not work on Microsoft Script Host (cscript.exe).

Example:

> type test.js
eval.apply(null, ["a=3;"]);
WScript.Echo(a);

> cscript test.js
Microsoft (R) Windows Script Host 버전 5.812
Copyright (C) Microsoft Corporation. All rights reserved.

3
KIM Taegyoon
  • 1,917
  • 21
  • 18
  • Neither of these seem to work in a cscript context (along with every other "answer" here which assumes we're in a browser). – BuvinJ Mar 17 '21 at 20:23
1

I know there will be lot of comments coming in with eval is evil and I agree with that. However, to answer your question, change your start method as follows:

function start(){   
  execute("ary = new Array()");   
  execute("ary.push('test');");  // This will cause exception: ary is not defined  
} 
Chandu
  • 81,493
  • 19
  • 133
  • 134