Use string to call function without eval() - javascript

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();

Related

How can I get the parameter names of a function stored in a variable?

See this code:
var method = function(service,worker){
//....
}
function getArguments(method){
//what I want is:
//print " the arguments of the method is 'service','worker'"
}
getArguments(method);
How can I get the names of the parameters from the variable?
I know method.arguments will not work when the method is not called.
You can call toString on the function, then use a regular expression to extract the argument list from the function definition. Here's a simple example:
function getArguments(method){
// strip off comments
var methodStr = method.toString().replace(/\/\*.*?\*\/|\/\/.*?\n/g, '');
var argStr = methodStr.match(/\(([^)]*)\)/);
alert(argStr[1].split(/\s*,\s*/g));
}
Demonstration

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.

How to define a javascript function with a name equal to a string

Let's say I'm given a string, and I want to define a function with a name of that string. How can I do this?
UPDATE:
I forgot to mention that I do not want to set an anonymous function to a property because I would also like to dynamically grab the function's name from inside the function ie. arguments.callee.name
Like this:
var functionName = "myfunction"
window[functionName] = function() {
// your function here
}
Depending on the requirements, maybe something like this would work:
var myFunctionGenerator = function(name) {return function(message) {
alert("hi, this is a function named '" + name + "'. The parameter passed is '" + message + "'.");
}}
var myFunction = myFunctionGenerator('some function name');
myFunction('a parameter');
// hi, this is a function named 'some function name'. The parameter passed is 'a parameter'.
If your declaring the function, use eval(). Just type a string representation of the argument your trying to execute for example:
eval("function name(){alert('a');}");
You can then call that method by normal convention, name();.
If you already have the function name and want to call that function with a string representation you can use the eval() method, although its not always optimal for performance. You will have this:
var fnName = "functionName";
var params = "param1";
var fnNameWithParams = "functionName("+params+")";
eval(fnNameWithParams);
A better approach may be:
var fnName = "functionName";
var params = "param1";
var fnToCall = window[fnName];
fnToCall(params);

How to call anonymus function from string

I have string containg anonymus function definition, but how i can call this. Lets say function is like so:
var fn_str = "function(){ alert('called'); }";
Tried eval, but got an error that function must have a name.
eval(fn_str).apply(this); // SyntaxError: function statement requires a name
You can use Immediately Invoked Function Expression:
var fn_str = "function(){ alert('called'); }";
eval('(' + fn_str +')();');
Immediately Invoked Function Expression
Another way is to use to a Function object (If you have the function body string):
var func = new Function("alert('called')");
func.apply(this);
You can create functions from strings using the Function constructor:
var fn = new Function("arg1", "alert('called ' + arg1);");
fn.apply(this)
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function
Found the solution: Put function in parentheses
var a = "(function(){ alert('called'); })";
eval(a).apply(this);

executing anonymous functions created using JavaScript eval()

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.

Categories

Resources