executing anonymous functions created using JavaScript eval() - javascript

I have a function and its contents as a string.
var funcStr = "function() { alert('hello'); }";
Now, I do an eval() to actually get that function in a variable.
var func = eval(funcStr);
If I remember correctly, in Chrome and Opera, simply calling
func();
invoked that function and the alert was displayed.
But, in other browsers it wasn't the case. nothing happened.
I don't want an arguement about which is the correct method, but how can I do this? I want to be able to call variable(); to execute the function stored in that variable.

How about this?
var func = new Function('alert("hello");');
To add arguments to the function:
var func = new Function('what', 'alert("hello " + what);');
func('world'); // hello world
Do note that functions are objects and can be assigned to any variable as they are:
var func = function () { alert('hello'); };
var otherFunc = func;
func = 'funky!';
function executeSomething(something) {
something();
}
executeSomething(otherFunc); // Alerts 'hello'

IE cannot eval functions (Presumably for security reasons).
The best workaround is to put the function in an array, like this:
var func = eval('[' + funcStr + ']')[0];

I realize this is old, but it was the only valid result coming up in my google searches for evaluating anonymous javascript function strings.
I finally figured out how to do it from a post on the jquery google group.
eval("false||"+data)
where data is your function string like "function() { return 123; }"
So far, I have only tried this in IE8 and FF8 (the browsers on my personal computer), but I believe jquery uses this internally so it should work just about everywhere.

Try
var funcStr = "var func = function() { alert('hello'); }";
eval(funcStr);
func();

Use the eval like this :
var func = eval('(' + funcStr + ')');

We solved this problem by preparing universal function parser that convert string to real JavaScript function:
if (typeof String.prototype.parseFunction != 'function') {
String.prototype.parseFunction = function () {
var funcReg = /function *\(([^()]*)\)[ \n\t]*{(.*)}/gmi;
var match = funcReg.exec(this.replace(/\n/g, ' '));
if(match) {
return new Function(match[1].split(','), match[2]);
}
return null;
};
}
examples of usage:
var func = 'function (a, b) { return a + b; }'.parseFunction();
alert(func(3,4));
func = 'function (a, b) { alert("Hello from function initiated from string!"); }'.parseFunction();
func();
here is jsfiddle

This is also ok.
var func = eval("_="+funcStr);

EVAL without eval()...
function evalEx(code){
var result,D=document,S=D.createElement('script'),
H=D.head||D.getElementsByTagName['head'][0],
param=Array.prototype.slice.call(arguments);
code='function evalWE(){'+code+'}';
S.innerText===''?S.innerText=code:S.textContent=code;
H.appendChild(S);
result=evalWE.apply(this,param);
H.removeChild(S);
return result
}
Usage Example:
ABC=evalEx('return "ABC"');
nine=evalEx('return arguments[1]+arguments[2]',4,5);

A simple example of defining a function as a string, eval()ing it, and passing in a parameter while immediately invoking the function (and then dumping the result to the console):
console.log('eval: %s', eval("(function(foo) { return foo.bar; })")({"bar": "12345"}));
This produces output like the following.
eval: 12345

What also works is
var myFunc = function(myParam){
// function body here
}

function-serialization-tools provides a function, s2f(), that takes a string representation of a function and returns it as a function.

Related

How to convert text to a function using JavaScript

I have a text string that is correctly formatted as a function and I would like to convert it to an actual function. The text string looks like:
function object_123(){
object_123_Action();
my_clicked(obj);
}
Apart from the word "function" and {}; all other text is dynamically constructed. i.e. It may never contain object_123_Action(), however, it will be something similar, basic function calls. The only issue will be the obj will need to be the object that the function is assigned to.
Basically, I need:
this.func = eval(func_txt); //to actually work.
Where func_txt is:
function object_123(){
object_123_Action();
my_clicked(this);
}
Your string contains a function declaration.
When evaluated, it creates a object_123 variable in the scope of eval (which you can then call later) and returns nothing.
If you want to assign the function to this.func then you need to convert the declaration into a function expression. You can do that by wrapping it in parens.
this.func = eval("(" + func_txt ")" );
var func_txt = "function object_123(){\
object_123_Action();\
my_clicked(obj);\
}";
this.func = eval("(" + func_txt + ")");
var obj = "...";
function object_123_Action() {
alert(1);
}
function my_clicked() {
alert(2);
}
this.func();
You can store your functions in an array on the object.
Then, loop though the functions in another function and execute them.
var myObj = { 'myfunctions': [ ] };
and to add functions:
myObj.myFunctions.push (function () { /*function code here*/ });
Or if you already have a named function:
myObj.myFunctions.push (nameOfFunction);
And to call all the functions, use this function (don't add this function to myObj)
function executeMyFunctions (myObj) {
for (var i = 0; i < myObj.myFunctions.length; i++) {
myObj.myFunctions[i]();
}
}
And if it's possible to avoid using eval, you should.
Try this:
function parseStringToFunction(func) {
func = func || '(function(){return null;})';
return (new Function('return ' + func)());
};
var stringifyFunction = '(function(a, b) { return a+b; })';
var callStringifyFunction = parseStringToFunction(stringifyFunction)(1, 2);
alert(callStringifyFunction); // results is 3
Also read this out: detail about eval() and new Function()
Try this-
$("<script type='text/javascript'></script>").html(func_txt).insertAfter($("script"));
This works:
assert( eval("(function(a, b) { return a+b; })")(1, 2) == 3 )
See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#eval_as_a_string_defining_function_requires_(and)_as_prefix_and_suffix
Simply wrap the function in parens.

Use string to call function without eval()

I want to pass a string to a function that then will use this string as a callback.
e.g.
app.on('notice', function(data) {
var callback = data.func; // this is a string
eval(callback + "()"); // trun string into an executable function
});
However I'm using this in an environment which prevents eval() from being used... How can I rewrite this to work without eval?
I've tried:
var self = this;
return function(){ self[callback]() };
But it doesn't call the function (and I don't get any errors)
Update: I forgot I also need to handle parameters:
e.g.
var params = ['param1', 'param2'];
eval(callback + "("+ params +")");
Use window object.
Replace your eval() call with :
window[callback]();
You could use a Function constructor .
var func = new Function("console.log('i am a new function')");
func();

Make object's properties available inside function

I would like to do the following.I have a code like this:
var obj = {
method : function() {}
};
var func = function() {
return method(); //method is undefined here
};
func(); // What to do here?
Is it possible to call func in a way that it will see the method inside from obj as it was given for example as a parameter. I want to use obj.method inside func, without writing 'obj.' before and without modifying func itself. Is there any hack possible to achieve this?
In other words, is it possible to force obj as a closure into func?
I tried:
with(obj) {
func();
}
But it doesn't work. Anyone, any ideas? Or is it the only option to get the body of the function as string, put 'with(obj)' inside it and then create a new function out of it?
Clarification:
Because this code will be in a helper class 'eval' is OK. Which I don't want is the modification of the function through .toString(), because browsers implement it differently.
This is a solution, using eval (MDN):
var obj = {
method : function() {console.log("it workes!");}
};
var func = function() {
return method(); //method is undefined here
};
var newfunc = (function (obj, func) {
var method = obj.method;
eval("var f = " + func.toString());
return f;
}(obj, func));
newfunc(); //it workes
Basically you're just creating a new scope with a local variable called method and re-evaluating the function body in this scope. So you're basically creating a new function with the same body. I don't really like this approach and I wouldn't recommend it, but considering your constraints, it might be the only solution.
And yes, it still requires you to write obj.method, but not inside of func. So I figured, it should be ok.
EDIT
So here is a version, in which you don't have to specify the property name manually:
var newfunc = (function (__obj__, __func__) {
for (var __key__ in __obj__) {
if (__obj__.hasOwnProperty(__key__)) {
eval("var " + __key__ + " = " + __obj__[__key__]);
}
}
eval("var __f__ = " + func.toString());
return __f__;
}(obj, func));
This also done by using eval().
Note that I changed all remaining local variables to a names containing underscores, to minimize the probability of name collisions with properties inside obj.
Note also that not all valid property names are valid variable names. You could have an object like this:
var obj = {
"my func": function () {}
}
But if you would use this object you would generate a syntax error with the above method, because it would try to evaluate:
var my func = ...
As apsillers said in the comment section, it gets even worse if you don't have control over the properties of obj. In this case you shouldn't use eval at all, because you would make cross-site scripting attacks very easy (example from apsillers):
var obj = {
"a; alert('xss'); var b": function () {}
}
would evaluate to 3 different statements:
var a;
alert('xss');
var b = function () {};
This is not possible unless you define method separately:
var obj = {
method : function() {}
},
method = obj.method;
// rest of code
This is because the method reference inside func() assumes the window. namespace; thus, without modifying func() itself, it can't be done sanely.
More clarified version based on basilikum's answer, and I've found a simplification with 'with':
var obj = {
method : function() { return "it workes!"; }
};
var func = function() {
return method(); //method is undefined here
};
(function (obj, func) {
with(obj) {
eval("var __res__ = (" + func.toString() + ")()");
}
return __res__;
}(obj, func));
>> "It workes!"

Is it possible for a JavaScript function to return its own function call as a string?

In JavaScript, is it possible for a function to return its own function call as a string?
function getOwnFunctionCall(){
//return the function call as a string, based on the parameters that are given to the function.
}
I want this function to simply return its own function call as a string (if it's even possible to do this):
var theString = getOwnFunctionCall(5, "3", /(a|b|c)/);
//This function call should simply return the string "getOwnFunctionCall(5, \"3\", "\/(a|b|c)\/")".
I put this one up on jsFiddle: http://jsfiddle.net/pGXgh/.
function getOwnFunctionCall() {
var result = "getOwnFunctionCall(";
for (var i=0; i < arguments.length; i++) {
var isString = (toString.call(arguments[i]) == '[object String]');
var quote = (isString) ? "\"" : "";
result += ((i > 0) ? ", " : "");
result += (quote + arguments[i] + quote);
}
return result + ")";
}
alert(getOwnFunctionCall(5, "3", /(a|b|c)/));
Note that this should work for your example, but still needs work for arbitrarily complex objects/JSON included as a parameter.
http://jsfiddle.net/WkJE9/4/
function DisplayMyName()
{
//Convert function arguments into a real array then let's convert those arguments to a string.
var args = [].slice.call(arguments).join(',');
// Get Function name
var myName = arguments.callee.toString();
myName = myName.substr('function '.length);
myName = myName.substr(0, myName.indexOf('('));
return(myName + " ("+ args + ")");
}
var functionText = DisplayMyName(5, "3", /(a|b|c)/) //returns DisplayMyName(5, "3", /(a|b|c)/)
alert(functionText);
Using the implicit arguments variable, you can extract both the function arguments and the function name:
function getOwnFunctionCall() {
var args = arguments; // Contains the arguments as an array
var callee = arguments.callee; // The caller function
// Use this to construct your string
}
Edit
Several comments note that callee is not something to be relied on. But if this is something you are going to do inside each of your methods, then just use the function name as you have defined it:
var functionName = "getOwnFunctionCall"; // But you can really just use it inline...
if you NEED to do it, and need to do it in global strict, and you don't want to hard-code the names:
function args(arg){
var me;
try{ badCAll654(); }catch(y){ me=String(y.stack).split("args")[1].split("\n")[1].trim().split("#")[0].replace(/^at /,"").split(" ")[0].trim() }
return me +"("+[].slice.call(arg).join(", ")+")";
}
function getOwnFunctionCall() {
"use strict";
return args(arguments);
}
getOwnFunctionCall(1,true, /dd/);
this can be a good debugging tool, but i would not recommend using it on production sites/apps; it's going to impact performance quite a bit. This pattern only works in chrome and firefox, but works under a global "use strict".
IE9 is less strict, so you can do the following:
function args(arg){
var me=arg.callee+'';
return me.split("(")[0].split("function")[1].trim() +"("+[].slice.call(arg).join(", ")+")";
}
function getOwnFunctionCall() {
"use strict";
return args(arguments);
}
getOwnFunctionCall(1,true, /dd/);
if you poly-fill the trim()s, it should also work in IE8.
if you don't use strict, you can do even more cool stuff like log the function that called the function that's being logged. you CAN even rip that function's source to find calls to the logged function if you want the names of the arguments and not just the values. Complex and worthless, but possible.
again, you should really use this only for debugging!
Based on your comment
I've been trying to find ways to prevent specific functions in eval
statements from being evaluated, and this is one potential solution
for that problem.
What you are asking for might not be what you really need. Why not just override the functions you want to prevent before evaling and restore them aferwards:
var blacklist = [ 'alert', 'setTimeout' ];
var old = {};
// Save the blacklisted functions and overwrite
blacklist.forEach(function(name) {
old[name] = window[name];
window[name] = function() {
console.log(name + ' has been disabled for security reasons');
}
});
eval('alert("Hello world")');
// restore the original functions
blacklist.forEach(function(name) {
window[name] = old[name];
});
is it possible for a function to return its own function call as a string?
No. You cannot extract by what expression you got your arguments into the function - you can only access their values. Of course you could simulate a call string with primitive values, but you never know whether they were passed to the function as a variable, a literal, or a whole expression.
Maybe, Mozilla's toSource method can help you with that.

Find out if function is anonymous or is defined in a object

I'm trying to write a helper method in JavaScript. It should act differently if one sends in a function or an reference to a function.
I want to like to use it like this:
helper('div', function () { return false; })
helper('div', obj.fn)
What I can't figure out is: how to inside the helper function tell the difference between the two?
I think it's due to that JavaScript first evaluates the obj.fn before it sends it in.
The only workaround I found is to send the obj.fn as an obj, i.e.
helper('div', { fn: obj.fn })
Then I can tell the difference between the two with typeof. But I really like some way to make it without the extra object declaration.
UPDATED *(AGAIN):
I thought that the toString() method might be your only way forward here. It doesn't however treat a reference of an anonymous object differently.
This code demonstrates that:
function acceptparam(fn){
console.log("fn.constructor = " + fn.constructor);
console.log("typeof fn = " + typeof fn);
console.log("fn toString " + fn.toString());
console.log("fn.prototype = " + fn.prototype);
console.log("fn.prototype.constructor = " + fn.prototype.constructor);
console.log("this[0] = " + this[0]);
console.log("---");
}
function empty(){
return ;
}
var x = {
y : function(){return;}
}
acceptparam(empty);
acceptparam(function(){return;});
acceptparam(x.y);
Very interesting question, without implementing your own solution I dont think you can do it, this post helps to explain why. Its about the parent child relationship only being one way.
http://codingforums.com/showthread.php?t=134855
I thought I'd add another alternative answer, mainly because I didn't want to add to the soup that is my other answer but also because it didn't go down to well with the stackoverflow voters that don't leave constructive comments ;-)
As an alternative to what you're trying to do, you could add a third parameter to the helper function:
function helper (tagName, fn, method)
{
if (method)
fn = fn[method];
//- Do rest of helper function here
}
//- Now if we pass an object method to helper function we can identify it properly
helper('div', obj, "fn"); // method is obj.fn
helper('div', function () { blah(); }); // Still works fine
Merely a suggestion and works as well as or even better than your current work-around.
You can use toString() to find out if the function is anonymous assuming it is declared as a named function and not an unnamed function assigned to a variable:
function jim () { var h = "hello"; }
function jeff(func)
{
var fName;
var inFunc = func.toString();
var rExp = /^function ([^\s]+) \(\)/;
if (fName = inFunc.match(rExp))
fName = fName[1];
alert(fName);
}
Will give you the name of the function if any.
jeff(function () { blah(); }); // alert: null;
jeff(function joe () { blah(); }); // alert: "joe";
jeff(jack); // "jack" if jack is function jack () { }, null if jack = function() {}
My previous edit referred to an IE quirk that didn't exist in other browsers and is no longer valid in IE as of version 9. However, you can still assign named functions as object properties using a named function expression:
var obj = {
fn: function namedFunction () { }
};
This works in all browsers, but IE 8 and lower don't adhere to the specification which says the function is only available by this name inside its own block.

Categories

Resources