Avoiding eval when executing js returns from ajax call

I want to make an ajax call that will return a json object. One of these properties of the JSON object will be a function string that must be executed in the client. I understand that this can easily be solved using eval, but, having seen the many disadvantages of eval, I would rather avoid it. My question is:

Can I somehow return some js code from the server and execute it without resorting to eval?

As required, here is a sample code:

Server (Node.js):

var testFunc = function() {
    alert('h1');
};

app.get('/testPack', function(req, res) {
    var template = jade.render('h1 hi');
    res.send({
        template : template,
        entity : testFunc.toString(),
        data : { 
            id: "OMG I love this"
        }
    });
});

Customer:

$(document).ready(function() {
    $.ajax({
        url: '/testPack',
        success: function(data) {
            $('body').append($(data.template))
            alert(data.data.id);
            var entity = eval(data.entity);
            entity();
        }
    })
})

Of course, a return function called entity will not do such stupidity, it will provide an API for the returned widget.

, javascript. .

+3
9

- ajax, script URL-, - RESTful, JavaScript ( JSON). , eval.

: script , . , script , onload (, , onload, IE script), , . ( ):

function test ()
{
    this.init = function ()
    {
        var script = document.createElement("script");
        script.type = "text/javascript";
        script.language = "javascript";
        script.src = "test.js";
        var me = this;
        window.callMe = function () { me.scriptReady(me); };
        var head = document.getElementsByTagName("head")[0];
        head.appendChild(script);
    };

    this.scriptReady = function (object)
    {
        serverResponse.call(object);
    };

    this.name = "From inside the object";

    this.init();
}

var t=new test();

:

function serverResponse()
{
    alert(this.name);
}

window.callMe();

serverResponse() "this". , :

function serverResponse()
{
    this.serverJSONString = { "testVar1": "1", "testVar2": 2 };

    function Test()
    {
        alert("From the server");
    }

    Test();
}

window.callMe();

, , . , JSON, , .

, , , , , .

P.S. IE, . IE, script .

P.P.S. , , , . , , : -)

+4

, , JavaScript JSON. . :

, : . eval. , , , , , JSON.

+1

, , .

json , . c d . - , , [ "property" ] accessor.

, jsFiddle: http://jsfiddle.net/WUY4n/1/

// This function is a child of the window object
window.winScopedFunction = function() {
    alert("ROCK THE WIN");    
}

// This function is a child of another object
var myObject = {
  myFunction : function() {
    alert("ROCK ON");
  }
};

// pretend that this json object was the result of an ajax call.
var jsonResultFromServer= {
    a : 1,
    b : 2,
    c : "myFunction", 
    d : "winScopedFunction" 
};

// you can call the local functions like so
myObject[jsonResultFromServer.c]();

window[jsonResultFromServer.d]();
+1

, , , eval.

Function , . :

new Function(code)();
+1

eval

, . eval. , .

, eval is evil. . , eval, , . " ".

,

, (, )?

script -, - , , , , - , , .

- script

, - , . , , , , , , , .

, - , , - , . ! . : ( ) , .

"script " .

, : , .

, , , , , , , . - , .

script, , : , . JSON , .

-

, : .

- .

+1

http://code.google.com/p/json-sans-eval/ - JSON, eval, JSON.parse , eval JSON.

+1

? , , , js , . , ! ( ?)

// your js file
var some_namespace = {
  some_function : function(a, b){
    // stuff
  }
}

// your server output
{
  some_other_data: "123",
  execute: {
    func: "some_namespace.some_function",
    params: [1, 2]
  }
}

// your ajax callback
function(r){
  window[r.execute.func].apply(this, r.execute.params);
}
0
source

You can use the trick Google does with the Google Chart.

<html>
<head>
  <script>
   function onWorkDone(data) {
    console.log(data);
   }
  </script>
  <script src="callback.js"></script>
</head>
</html>

Then your callback.js:

function doWork(callback) {
  callback({result: 'foo'});
}
doWork(onWorkDone);

Basically, your script will call onWorkDonewhen completed doWork. Here you can see a working example: http://jsfiddle.net/ea9Gc/

0
source

I had the same question, and I fixed it like this:

File: functions.js.php? f = 1.3

$functions=array(
    'showMessage' => 'function(msg){ alert(msg); }',
    'confirmAction' => 'function(action){
                          return confirm("Are you sure you want to "+action+"?");
                        }',
    'getName' => 'function getName(){
                    return prompt("What is your name?");
                  }'
);

$queried = explode($_REQUEST['f']);

echo 'var FuncUtils = {'; // begin javascript object

$counter=1;
foreach($functions as $name=>$function){
    if(in_array($counter, $queried))
        echo '"'.$name.'":,'.$function.',';
    $counter++;
}

echo '"dummy":null };'; // end javascript object

File: data5.json

{
    "action" : ['confirmAction','exit']
}

File: test.js

$(document).ready(function(){
    $.getScript('functions.js.php?f=1,3');
});

function onBeforeExit(){
    $.getJSON('data5.json', function(data) {
        var func = data.action.shift();
        FuncUtils[func].apply(null, data.action);
    });
}
0
source

All Articles