72

I have following javaScript "class":

A = (function() {
   a = function() { eval(...) };
   A.prototype.b = function(arg1, arg2) { /* do something... */};
})();

Now let's assume that in eval() I'm passing string that contains expression calling b with some arguments:

 b("foo", "bar")

But then I get error that b is not defined. So my question is: how to call eval in context of class A?

mnowotka
  • 16,430
  • 18
  • 88
  • 134
  • 9
    Do you really *need* to use eval? That's usually a sign of bad code. – NullUserException Dec 06 '11 at 16:15
  • 1
    See also http://stackoverflow.com/questions/1199110/whats-a-more-secure-alternative-for-eval-when-i-just-want-to-call-a-function – Vincent Mimoun-Prat Dec 06 '11 at 16:19
  • What does this function do? I'm sure it can be replaced with something that isn't `eval`. – gen_Eric Dec 06 '11 at 16:35
  • 43
    Yes, unfortunately I have to... You can trust me I don't want but I don't have any other choice. So please treat this question like interesting case instead of suggesting to get rid of eval. – mnowotka Dec 06 '11 at 16:38
  • @mnowotka: Can you show us exactly what is being `eval`ed? Because it should work. See this example: http://jsfiddle.net/9vyUu/ – gen_Eric Dec 06 '11 at 17:03
  • 3
    There are so many errors in this snippet. Please post functional code. What should this code do? Read this article about prototyping in JS: http://www.2ality.com/2011/11/javascript-classes.html – frank_neff Dec 06 '11 at 17:05
  • 1
    You can pass `this` and further parameters to your evaled code by using: `Function.constructor(evalCode).call(thisContext, a,b, ...)` instead of `eval`. – Lea Rosema Nov 30 '15 at 13:17
  • I've stumbled upon [boa](https://github.com/boa-dev/boa) and then try to find other alternatives (e.g. JSC.js). [This](https://github.com/mbbill/JSC.js/issues/2#issuecomment-568301675) comment made the thoughts click in my head. Maybe your use-case was / is like mine and that you found those useful. – ozanmuyes Oct 14 '21 at 00:08

18 Answers18

95

Actually you can accomplish this with an abstraction via a function:

var context = { a: 1, b: 2, c: 3 };

function example() {
    console.log(this);
}

function evalInContext() {
    console.log(this);        //# .logs `{ a: 1, b: 2, c: 3 }`
    eval("example()");        //# .logs `{ a: 1, b: 2, c: 3 }` inside example()
}

evalInContext.call(context);

So you call the function with the context you want and run eval inside that function.

Oddly, this seems to be working for me locally but not on Plunkr!?

For a succinct (and arguably succulent ;) version you can copy verbatim into your code, use this:

function evalInContext(js, context) {
    //# Return the results of the in-line anonymous function we .call with the passed context
    return function() { return eval(js); }.call(context);
}

EDIT: Don't confuse this and "scope".

//# Throws an error as `this` is missing
console.log(evalInContext('x==3', { x : 3}))

//# Works as `this` is prefixed
console.log(evalInContext('this.x==3', { x : 3})) 

While one could do this:

function evalInScope(js, contextAsScope) {
    //# Return the results of the in-line anonymous function we .call with the passed context
    return function() { with(this) { return eval(js); }; }.call(contextAsScope);
}

to bridge the gap, it's not what OP's question asked and it uses with, and as MDN says:

Use of the with statement is not recommended, as it may be the source of confusing bugs and compatibility issues. See the "Ambiguity Contra" paragraph in the "Description" section below for details.

But it does work and isn't too "bad" (whatever that means), so long as one is aware of the oddnessess that can arise from such a call.

However, ESM enables strict mode by default, which you can circumvent with the Function constructor like this:

"use strict";

function evalInScope(js, contextAsScope) {
  return new Function(`with (this) { return (${js}); }`).call(contextAsScope);
}

console.log(evalInScope("a + b", { a: 1, b: 2 })); // 3
kungfooman
  • 4,473
  • 1
  • 44
  • 33
Campbeln
  • 2,880
  • 3
  • 33
  • 33
  • 7
    Which browser (version) did you try this? It does not work, according to the spec (and in every modern browser) you are getting `undefined` (or the global window object in sloppy mode functions) for the `this` value in `example`. – Bergi Oct 18 '16 at 13:09
  • 1
    I faced a similar problem to this and found the above does not work. I have posted a possible solution that I found here: http://stackoverflow.com/a/40109254/1972493 – Joe Oct 18 '16 at 13:15
  • @Bergi and @Joe - I just retested this with Firebug in this window with Firefox 49.0.2 and it still works fine?! Same deal with Chrome 54.0.2840.71 (64-bit), Opera 40.0 and Safari 10.0.1 (11602.2.14.0.7). In every case, I opened the console, ran the `evalInContext` function definition, then defined an object `var neek = { camp: true, bell: false }` then called the function like so: `evalInContext("this.camp", neek)` and `evalInContext("this.bell", neek)` which returned `true` and `false` respectively... How are you guys/gals doing it? – Campbeln Nov 01 '16 at 19:05
  • @Campbeln I just ran the code that you posted in your answer. What you posted in your comment makes sense, but `evalInContext("example()", neek)` wouldn't work either. – Bergi Nov 01 '16 at 22:15
  • @Bergi Humm... passing the call into another function (`example` as above) does seem to be barfing back the window rather than `var context`... humm... why... – Campbeln Nov 03 '16 at 16:49
  • Because it's a simple call and behaves like that. The `this` context in the scope where `eval` is called is irrelevant. `eval("example()")` is the same as `example()` for all purposes. – Bergi Nov 03 '16 at 16:56
  • But it didn't behave that way on writing the answer!? The `eval`ed function had the expected `this` context. I have a few projects that use this concept to function, so I'll need to test those to make sure nothing is broken. – Campbeln Nov 03 '16 at 16:59
  • Turns out this isn't exactly correct. Take a look at http://stackoverflow.com/questions/40107919/javascript-eval-in-context-without-using-this-keyword for more. – Liron Yahdav Mar 13 '17 at 18:39
  • This logs `Object { a: 1, b: 2, c: 3 }` and `Window`. – Teemoh Mar 27 '17 at 17:51
  • 1
    You should really update your answer to reflect the correct example which you provide in your comment. – papiro Mar 13 '19 at 17:04
  • I guess `call()` does not overwrite the `window` object? `evalInContext("window", {"window": 1})` failed to overwrite `window`. – est Mar 03 '20 at 13:34
  • 1
    @est `evalInScope("window", { window: 1 })` returns `1` while `evalInContext` would need to use `this.window`(e.g. `evalInContext("this.window", { window: 1 })`) to return `1`. – Campbeln Apr 24 '20 at 07:51
  • 1
    @Campbeln that explains everything. Thanks! – est May 06 '20 at 07:35
  • load({},'class MyClass {//define here}', 'MyClass') public load(context,js,classname){ js += `(function() { return new ${classname}();})()`; return function() { return eval(js); }.call(context); } – JonathanC Dec 31 '20 at 15:12
43

How to call eval in a given context? 3 words. Use a closure.

var result = function(str){
  return eval(str);
}.call(context,somestring);

Bam.

user3751385
  • 3,752
  • 2
  • 24
  • 24
  • 3
    what an elegant solution – Chad Cache Oct 17 '15 at 20:35
  • What is the purpose of `somestring` here? – Wilt Nov 20 '15 at 15:45
  • 2
    "somestring" is the code you wish to run with the eval command. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call – user3751385 Nov 22 '15 at 23:32
  • 4
    Note that the expression in somestring must access the context properties using 'this', like this.property. Otherwise you get a property is not defined ReferenceError. var context = {'live-usa': 'no', 'alcohol': 'never', 'height': '65', 'weight': '140' }; var expression = "this.height == '' || this.weight == ''"; var result = function(str){ return eval(str); }.call(context, expression); // returns false in this case. – Ezward Jan 25 '17 at 23:57
  • how to disable access to global variables within the context? like 'window' 'document' – PeiSong Mar 27 '21 at 07:18
18

Edit

Even though, eval.call and eval.apply do not force the context to be passed in correctly, you can use a closure to force eval to execute in the required context as mentioned in the answers of @Campbeln and @user3751385

My original answer

This is not possible. Eval is called only in the local context(is used directly) or in the global context (even if you use eval.call).

For example, a = {}; eval.call(a, "console.log(this);"); //prints out window, not a

For more information, look at this great article here

everconfusedGuy
  • 2,709
  • 27
  • 43
  • 2
    Um... this is not entirely correct. You can execute `eval` with a particular context, where `this` === `theContext` you pass in (`{ neek: true }` for example). The trick is you have to `.call` another function which then calls `eval`, you cannot `.call` `eval` directly and accomplish this as in your example. Check out my answer below on how to accomplish this. – Campbeln Nov 04 '14 at 23:31
  • No, no, ... This can be done quite easily as noted in my response below. – user3751385 Nov 29 '14 at 17:40
9

definitely not the right answer, and please do not use with statement, unless you know what you're doing, but for the curious, you can do this

Example

    var a = {b: "foo"};
    with(a) {
        // prints "foo"
        console.log(eval("b"));  
        
        // however, "this.b" prints undefined
        console.log(eval("this.b"));
    
        // because "this" is still the window for eval
        // console.log(eval("this")); // prints window

// if you want to fix, you need to wrap with a function, as the main answer pointed out
        (function(){
          console.log(eval("this.b")); // prints foo
        }).call(a);     
    }
    
    // so if you want to support both    
    with (a) {
     (function (){
        console.log("--fix--");
       console.log(eval("b")); // foo
        console.log(eval("this.b")); // foo
      }).call(a);
    }

with is the failed attempt to create block scopes within functions, kind of what the ES6's let is designed to do. (but not exactly, open and read the resource links)

bentael
  • 1,987
  • 2
  • 21
  • 27
  • 4
    I think this answer is absolutely fine. The with statement is the perfect solution to this problem. It's only if you're using 'with' everywhere or in large scopes that it ambiguity can be a problem. :) – CodeAndCats Apr 10 '15 at 11:24
  • 2
    This is also the only solution that allows you to refer to values without the need for `this`. – Brett Ryan Dec 13 '18 at 08:07
7

So here we are in 2020 and I had this requirement and unfortunately most of the answers are simply not fit for the task.

You can probably skip this part but to explain the situation... here's a more complete answer.

Calling eval is bad... And here I am trying to do exactly that.. Not because I want but because someone forced me to do that... my other option would be to compile extract and AST and eventually evaluate the context of a value... But eval is exactly the tool for the task besides its own evil nature...

So here we go, the mdn documentation:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval

In short, eval used to work and now it's made more difficult to use as the context of evaluation will become the global context so in some case it's impossible to get this. And for some reasons, it didn't look like it could get the this as evaluation context using the answers from this question. So reading further we reach the second part of the article..

Second part of the articles starts with "Never use eval()!", message received! Reading further we come to this:

Fortunately, there's a very good alternative to eval(): simply using window.Function().

Ok good!

So looking at the code that seamed very good... Most of the example simply create a function call it and throw it away. This is pretty much how eval works so you could probably do that too...

But for me, the eval context can be reused and potentially quite often so I came up with this.

function create_context_function_template(eval_string, context) {
  return `
  return function (context) {
    "use strict";
    ${Object.keys(context).length > 0
      ? `let ${Object.keys(context).map((key) => ` ${key} = context['${key}']`)};`
      : ``
    }
    return ${eval_string};
  }                                                                                                                   
  `
}

This compiles a function that receives a context to be evaluated given a specific context. It's useful for cases where you know that the evaluation context will always contains a certain set of keys...

The first line of the function generate a list of declared variables on the local scope by taking values from the context passed as a parameter.

This will render JS code that look like this given a context: {a: 1, b: 2}

let a = context['a'], b = context['b'];

The second line is the context you want to evaluate so for something like this 'a + b'

It would render the following code:

return a + b

All in all, there is this utility method:

function make_context_evaluator(eval_string, context) {
  let template = create_context_function_template(eval_string, context)
  let functor = Function(template)
  return functor()
}

That simply wrap it up and return the functor we need...

let context = {b: (a, b) => console.log(a, b)}
let evaluator = make_context_evaluator("b('foo', 'bar')", context)
let result = evaluator(context)

The nice thing about it is that if you want to keep using the evaluator as you know you won't be changing the evaluation context much... Then you can save the evaluator and reuse it with different context..

In my case it's to evaluate a context based on some records so the field set is the same but the values are different... So the method can be reused without having to compile more than one method... On the other plus side, it's supposedly faster than using eval and we're not evaling anything. And if the value passed to the Function would try to used thing outside of its scope... it would be less harmful than eval... For example, it has access to the global scope but shouldn't have access to the lexical scope. In other words...You're limited to the global scope, and the this passed to the call argument.

And then if you really wanted to use it as an eval like function you could do this:

function create_context_function_template(eval_string, context) {
  return `
  return function (context) {
    "use strict";
    ${Object.keys(context).length > 0
      ? `let ${Object.keys(context).map((key) => ` ${key} = context['${key}']`)};`
      : ``
    }
    return ${eval_string};
  }                                                                                                                   
  `
}

function make_context_evaluator(eval_string, context) {
  let template = create_context_function_template(eval_string, context)
  let functor = Function(template)
  return functor()
}

function eval_like(text, context={}) {
   let evaluator = make_context_evaluator(text, context)
   return evaluator(context)
}

Here's an example of how to use:

< eval_like("fun + 2", {fun: 1})
> 3

Or you could even pass just an object like this.

> this.fun = 1
> eval_like("fun + 2", this)
> 3

You can pass expressions like a function declaration but...

> eval_like("() => fun", {fun: 2})()

It will work but it's important that everything that needs to be evaluated is in the context. If the context value aren't there, Javascript will try to take them from the global objects if I'm not mistaken.

So in order to work properly you have to be certain that no variable in the code is taken from the local scope.

Loïc Faure-Lacroix
  • 13,220
  • 6
  • 67
  • 99
7

Here is an article which discussing running eval() in different contexts:

http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context

Usually you do it with eval.call() or eval.apply().

Here is also information regarding eval() and its use cases:

https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/eval

gen_Eric
  • 223,194
  • 41
  • 299
  • 337
Mikko Ohtamaa
  • 82,057
  • 50
  • 264
  • 435
  • 2
    Stopped reading the first article at "eval is handy", and the second one doesn't mention any use cases for eval but rather how to replace the use of eval in situations where the common novice mistake is to use eval. – Esailija Dec 06 '11 at 16:24
  • 1
    `eval.call` gave me an error: `EvalError: The "this" object passed to eval must be the global object from which eval originated`. – gen_Eric Dec 06 '11 at 16:26
  • @Esailija: I purposely linked MDN article which dicusses how to workaround the eval use cases. The author of the question does not mention why he wants to use eval, so I assume he knows what he is doing. – Mikko Ohtamaa Dec 06 '11 at 16:42
  • @MikkoOhtamaa: I assume he doesn't know what he's doing since he's using `eval` in the first place. – gen_Eric Dec 06 '11 at 16:51
  • @Esailija: Sometimes `eval` is *the* answer. The first article explains why he's using it (though to solve his issue, he could have just done `new Function(src)()`). – RightSaidFred Dec 06 '11 at 16:53
  • @Rocket: What did you give as the *thisArg* for `.call()`? – RightSaidFred Dec 06 '11 at 16:54
  • @RightSaidFred: I disagree, there is always a way to replace an `eval` call with "better" code. The article explains why he's using it, yes, but that doesn't mean it's the best (or accepted) answer. The `eval` can be replaced here if we knew exactly what the function was doing. – gen_Eric Dec 06 '11 at 16:55
  • @Rocket: I don't mean *the* answer to this particular question, or that this answer should be accepted. I mean there are some situations where eval is the way to go. – RightSaidFred Dec 06 '11 at 16:57
  • @RightSaidFred: I still disagree. I don't think there is ever a situation where `eval` is the way to go. Can you show an example where you cannot replace the `eval` with "better" code? – gen_Eric Dec 06 '11 at 16:58
  • @Rocket: When code is provided from an external source, say input from a user, or a text file, and that code should be invoked, you need to eval it somehow (here I'm including the `Function` constructor as a means of evaling). – RightSaidFred Dec 06 '11 at 17:00
  • @RightSaidFred: True, that's one example, but that's a very rare case, and I'm pretty sure `new Function` uses `eval` anyway. I think you could also make a new ` – gen_Eric Dec 06 '11 at 17:01
  • 2
    @Rocket: Yes, it is rare, certainly in a browser environment. In something like NodeJS, its module system works by concatenating the code from a file into an opening and closing string, then evaling it. jsFiddle is probably another example, but I'm assuming. And yes, I'd assume `new Function` uses `eval`, or at least shares code under the hood with eval. Though there are differences. – RightSaidFred Dec 06 '11 at 17:04
  • @RightSaidFred: I've never used NodeJS, and this is a browser environment, I'm assuming. jsFiddle actually makes a new ` – gen_Eric Dec 06 '11 at 17:05
  • 2
    @Rocket: Not sure if this is a browser environment, but probably a safe bet. By the way, your jsFiddle didn't work because you weren't passing the `window` object. – RightSaidFred Dec 06 '11 at 17:08
  • @RightSaidFred: Ah, so you can only set `this` to `window` it seems, not anything else. – gen_Eric Dec 06 '11 at 17:10
  • 1
    @Rocket: I think you're right about jsFiddle. Since they're getting a new window with the frame, they just wrap your code in a ` – RightSaidFred Dec 06 '11 at 17:14
6

This solved my problem.

 function evalInContext(js, context) {
    return function(str){
        return eval(str);
    }.call(context, ' with(this) { ' + js + ' } ');
}

for implementation similar to "Dom-if"

<template if="{{varInContext == ''}}"> ... </template>

Example

var myCtx = {table: 'Product', alias: 'ProductView'};
evalInContext(' table == "" ', myCtx); //#false
evalInContext(' alias == "ProductView" ', myCtx); //#true
Ilario Junior
  • 378
  • 4
  • 9
3
var evalWithinContext = function(context, code)
{
    (function(code) { eval(code); }).apply(context, [code]);
};
evalWithinContext(anyContext, anyString);
Eigendrea
  • 320
  • 4
  • 14
2

You can use my library https://github.com/marverix/meval .

const meval = require('meval');

console.log(
  meval('item.a + item.b * 5', { item: { a: 2, b: 3 } })
);

// outputs: 17
marverix
  • 7,184
  • 6
  • 38
  • 50
  • It has been created for simple one-liners, and not whole JS libraries. So please do not downvote the answer. – marverix Apr 20 '21 at 05:29
2

Folks, I think that I have the definitive answer. It works on both JavaScript (Browsers) and NodeJs.

function evalInContext(Context,toEval){
  return eval(`(function Main(){${toEval}})`).call(Context);
}

var context = {a:42,b:82,c:103};
var toEval = "return this";

console.log(evalInContext(context,toEval));//{"a": 42, "b": 82, "c": 103}

Tested on Node v12.16.1, Node v14.7.0, Firefox v79.0 and Google Chrome v84.0.4147.105

1

Another Bam!

eval('(function (data) {'+code+'})').call(selector,some_data);

This example will keep yours context and send some data. In my case, is a some DOM selector

Artur
  • 211
  • 2
  • 6
1

I was struggling with this for a while in Angular, and found this answer the most useful. I was trying to implement some existing code which use 'with', not allowed by strict. My 'knife and fork' solution to not having to use 'this.' inside the expression I wanted to evaluate, and avoiding 'with' and 'eval' was:

let evalInContext = function (js, context) {
    let keys = Object.keys(context);
    //let code = 'function it(){';
    let code = '';
    for (let i = 0; i < keys.length; i++){
        code += 'let '+keys[i]+' = window._evalincontextobj.'+keys[i]+';\n';
    }
    code += 'return (';
    code += js;
    code += ')';//}\n return it();';
    window['_evalincontextobj'] = context;
    let res = Function(code)();
    console.log(js+' = '+res);
    delete window['_evalincontextobj'];
    return res;
}

This is working for expressions like (watched === 'hello') where 'watched' is a member of context.

Simon H
  • 373
  • 4
  • 7
1

This seems partly a duplicate of Specify scope for eval() in JavaScript? So I figured I'd cross-post my answer in case it's helpful for anyone looking specifically for setting the scope of an eval.

My version of the Function constructor based solution with modern syntactic sugar and what I think is a good solution to avoid polluting the scope with the internal variable containing the evaluated text. (By sacrificing the this context, on which properties can be deleted even inside use strict; code)

(if you want to soft-block/remove-from-scope certain global objects/methods, you can just add them to the scope as undefined and they'll be overridden (never use this for untrusted code, there's always ways around it))

class ScopedEval {
    /** @param {Record<string,unknown>} scope */
    constructor(scope) {
        this.scope = scope;
    }
    eval(__script) {
        return new Function(...Object.keys(this.scope),`
                return eval(
                    '"use strict";delete this.__script;' 
                    + this.__script
                );
            `.replace(/[\n\t]|  +/g,'')
        ).bind({__script})(...Object.values(this.scope));
    }
}

Personally I prefer being able to separate when I add or adjust the scope and when I eval some code, so this could be used like below.

 class ScopedEval {
    /** @param {Record<string,unknown>} scope */
    constructor(scope) {
        this.scope = scope;
    }
    eval (__script) {
        return new Function(...Object.keys(this.scope), `
                    return eval(
                        '"use strict";delete this.__script;' 
                        + this.__script
                    );
                `.replace(/\t/, ''))
            .bind({
                __script
            })
            (...Object.values(this.scope));
    }
}
const context = {
    hi: 12,
    x: () => 'this is x',
    get xGet () {
        return 'this is the xGet getter'
    }
};

const x = new ScopedEval(context)
console.log(x.eval('"hi = " + hi'));
console.log(x.eval(`
    let k = x();
    "x() returns " + k
    `));
console.log(x.eval('xGet'));

x.scope.someId = 42;
console.log(x.eval('(() => someId)()'))
joshhemphill
  • 492
  • 6
  • 20
0

What worked for me was using Function constructor and calling it in specified context:

var o = {
  x: 10
}

(new Function(`console.log(this.x)`)).call(o);

This somehow doesn't work in browser's console but works elsewhere.

Rytis Alekna
  • 1,387
  • 7
  • 17
0

Includes context plus a function plus an expression. The context must be a flat structure (no nested elements) and the function must be referred to as 'fn' inside the string expression. Answer prints 11:

var expression = "fn((a+b)*c,2)";
var context = { a: 1, b: 2, c: 3 };
var func = function(x,y){return x+y;};

function evaluate(ex, ctx, fn) {
return eval("var "+JSON.stringify(ctx).replace(/["{}]/gi, "").replace(/:/gi, "=")+", fn="+fn.toString()+";"+ex);
}

var answer = evaluate(expression, context, func);
console.log(answer);
Moika Turns
  • 677
  • 11
  • 17
0

For node.js env you can use safe-eval to evaluate in context, eg this (taken from https://www.npmjs.com/package/safe-eval):

// your own context API - access to Node's process object and a custom function
var code = '{pid: process.pid, apple: a()}'
var context = {
  process: process,
  a: function () { return 'APPLE' }
}
var evaluated = safeEval(code, context) // { pid: 16987, apple: 'APPLE' }
igorludi
  • 1,519
  • 2
  • 18
  • 31
0

To calling "eval" in particular context use "call" method:

var myscript = 'console.dir(this)';
context1 = document.querySelector('body');
context2 = document.querySelector('div');

// This execute myscript in context1=body
eval('(function(){'+ myscript +'})').call(context1);

// This execute myscript in context2=div
eval('(function(){' + myscript + '})').call(context2);
Dmitry Shashurov
  • 1,148
  • 13
  • 11
0

I'd prepare a string with respective code - a call of IIFE that contains our variables extracted from passed context + code to execute:

function exec(code, context) {
    // map object to variable declarations
    // e.g., {a: 1} to const a = 1;
    const ctx = Object.entries(context).map(([k,v]) => {
        const val = typeof v === 'string' ? `"${v}"` : v;
        return `const ${k} = ${val};`
    }).join('');
    
    return eval(`
        (function () {
            ${ctx}
            return ${code};
        })()
    `);
}

and our function in action:

exec('a + b', {
  a: 10,
  b: 20
})
// 30
exec('name.toUpperCase() + "!"', {
  name: 'John'
})
// 'JOHN!'

HOW IT WORKS

We convert passed context into JS code that declares variables. For example, {a: 10, b: 20} becomes const a = 10; const b = 20;. It's achieved with the use of the map() method. If a value is a string, we wrap it into "" so that eval() knows it's a string rather than a reference to a variable.

Below that we just put code to execute. Everything is contained in a closure - IIFE, a function that fires immediately.

The final string is passed to the eval(). That's it.

UPDATE

Full implementation can be found here on my GH