Chris
Chris

Reputation: 2465

Using JavaScript's eval() with multiple dependent functions

How do I load dynamic dependencies into an eval() call? (If at all possible)

I am trying to run a call to eval() using multiple functions but I can't seem to get it to work. ie:

function foo() {
    return bar;
}

function foo2() {
    return foo();
}

Ideally, what I want to work is:

eval("
    (function() { 
        function foo() {
            return bar;
        }

        return foo(); 
     }())
");

But I keep getting an error that foo is not defined.

I know that if foo() is defined in the html of my page, then I can use eval() to write a function that is basically foo2() and get the result I want:

eval("
    (function() { 
        return foo(); 
     }())
");

But I want to be able to change both functions and still be able to call foo2() which will always reference foo(). Is this possible? What are some ways I could get this working?

Upvotes: 1

Views: 4040

Answers (4)

NorseGaud
NorseGaud

Reputation: 771

I know this is old, but I found a way to do it. You have to have \ at the end of each line and escape quotes:

var canvas = document.createElement('canvas')
canvas.id = 'dailyTotalUsersCreated';
canvas.setAttribute('class', `bar dailyChart`)
var container = document.querySelector(`#daily`)
container.appendChild(canvas)
eval(` \
    var ${canvas.id} = new Chart('${canvas.id}', { \
        type: 'bar', \
        data: { \
            labels: [${lastSevenDays.map(obj => `"${new Date(obj.Date).toDateString()}"`)}], \
            datasets: [
                { \
                    label: 'Total Voice Users Created', \
                    data: [${lastSevenDays.map(obj => `${obj.Values.filter(obj => { return obj.Name === "Users Created" }).map(obj => totalUsersCreated - obj.Value)}`)}], \
                    backgroundColor: ['#3e95cd','#8e5ea2','#3cba9f','#e8c3b9','#c45850','#facb48','#384d3f','#247BA0','#F3FFBD','#FF1654'], \
                } \
            ] \
        }, \
        options: { \
            plugins: { \
                datalabels: { \
                    labels: { \
                        title: { \
                            color: 'black' \
                        } \
                    } \
                } \
            }, \
            scales: { \
                yAxes: [{
                    stacked: false,
                    gridLines: {
                        display: true,
                        color: "rgba(255,99,132,0.2)"
                    },
                    ticks: {
                        beginAtZero: true
                    }
                }]
            } \
        } \
    }); \
`);

Upvotes: 0

bormat
bormat

Reputation: 1379

try to use the syntax var foo = function(){} instead of function foo(){} in your eval, I don't know how you make multiline js string it doesn't exist, but an ";" beetween instruction for eval

Upvotes: 0

ibrahim mahrir
ibrahim mahrir

Reputation: 31692

Try and type this into the textarea:

function hello(name) {
  alert("hello" + name);
}

Then func will be a reference to hello (func == hello). Then you can use func to test the testcases like it was hello for example.

var ta = document.getElementById("code");

function run() {
  var code = "(function() { return " + ta.value + "; })()"; // code that will return a reference to the function typed by the user
  
  var func = eval(code); // func will be the function the user typed in the textarea
  
  func("me"); // you can call it like you want
}
<textarea id="code"></textarea>
<button onclick="run()">Run</button>

Upvotes: 4

Bergi
Bergi

Reputation: 664650

Yes, that is possible, just make sure that your evaled code overwrites the original functions with the new declarations, typically in the global scope.

Upvotes: 0

Related Questions