Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inverse operation for Javascript's Function.toString()

Tags:

javascript

For Javascript application I need to be able to let the user save the state of an object. This involves saving a set of custom functions that were previously created dynamically or through a GUI, and loading these stored functions later. Essentially I need to serialize and unserialize functions.

Right now I achieve the serialize part by using the Function object's .toString() method:

func.toString().replace('"', '\"').replace(/(\r)/g, ' ').replace(/(\n)/g, ' ').replace(/(\t)/g, ' ')

This gives me "serialized" functions like this beauty (note that the function is unnamed):

"function (someParameter) {this.someFunctionName(return 'something';}"

Unserializing this is where I struggle. My current best solution for unserializing the functions is this:

var func = eval( 't =' +  so.actions[i].func);

Note how I prepend the serialized function with t = before calling eval() on it. I don't like doing this because it creates a global variable but I cannot find a way around it. When not prepending this, I receive a "SyntaxError: Unexpected token (". When prepending var t =, eval() does not return the function but undefined.

Are there alternative ways to "unserialize" an unnamed function?

PS: I am aware of the security implications of using eval() on user input. For the foreseeable future I am the only user of this software, so this is currently a non-issue.

like image 582
jonemo Avatar asked Oct 16 '11 01:10

jonemo


1 Answers

You could use the Function constructor to avoid creating a global variable:

var func = Function("return " + so.actions[i].func)();

This is equivalent to:

var func = eval("(function () { return " + so.actions[i].func + " })()");

One thing to be wary of is the surrounding closure which you won't be able to capture, so variables inside the function will "change" when you serialize and de-serialize.

edit

I'm not thinking, you can of course just do:

var func = eval("(" + so.actions[i].func + ")");
like image 65
Conrad Irwin Avatar answered Sep 20 '22 10:09

Conrad Irwin