views:

105

answers:

6

Hi, I would like to call a function whose name I have in a variable.

For example:
I get the string "pageTracker._trackpageview('/url/page1.page'); " dynamically and assign it to a variable as below

var myFunction = pageTracker._trackpageview('/url/page1.page');";

Now when I submit the page I want to execute the function which is in variable myFunction.

Thank you all.

A: 

You can make use of eval in javascript..

var myFunction = "pageTracker._trackpageview('/url/page1.page');";
//...
eval(myFunction);
Quintin Robinson
+1  A: 

You can do this with the JavaScript eval() function. Just be careful about controlling the value passed to eval() as it will execute whatever string it is given.

eval("pageTracker._trackpageview('/url/page1.page');");
Nathan Taylor
+1  A: 

You are not simply trying to execute a function whose name you have but a complex line of code with a receiver, a method name and a literal string argument. The only way to execute an arbitrary snippet of codes is with eval() But eval() is dangerous. If you're not very careful, someone can pass malignant code to your script that will be executed inside the eval() call.

Alexandre Jasmin
Thnks for your reply. The function passed to the eval function is set by the adminsitrator so I dont have to worry about maligant code.
+1  A: 

Solution: Wrap the function

//define:
var myFunction = function (){pageTracker._trackpageview('/url/page1.page');}

//call:
myFunction();


Full Example:

<html>
   <head>
      <script type="text/javascript">
         var foo = function (){alert('bar');}
      </script>
   </head>
   <body onload="foo();"> </body>
</html>
vol7ron
Incorrect. The function invocation is in a string.
Emtucifor
correct, take the string out.
vol7ron
probably misread the question like i did. This assumes the page tracker string is already set or is part of a list of possibilities and not truly dynamic. This example wouldn't work then. It would have to be done with the ever deadly eval.
fleces
@fleces: you're right, i may have to delete this, but the original question only has one quote, which doesn't show a string and the asker says, `Now when I submit the page I want to execute the function which is in variable myFunction.` which makes it seem like we understood correctly.
vol7ron
+3  A: 
function functionFromString(funcDef) {
   try {
      return (new Function("return function() {" + funcDef + "};"))();
   } catch (e) {
      alert(e);
      return (function() {});
   }
}

var myFunction = "pageTracker._trackpageview('/url/page1.page');";

var realFunction = functionFromString(myFunction);
realFunction();

Why do it this way?

  1. Just doing eval runs the function right away. If there are errors thrown in the called function itself we can't tell the difference between that and an error in parsing. So by creating a function out of the text, we can separate when we parse it from when we execute it.

  2. Just using newFunction = Function(myFunction) won't compile it, so it's slower. So using new Function() to return a function (that in turn creates a function) is our trick. We could use eval this way, too, but I like new Function better.

What others have said about being really careful with eval (and new Function()) is true. It can be an opening for malicious script.

Emtucifor
A: 

But this way, you cannot check if parameter is correct url, or encode it ect. And I avoid eval as hell for known reasons.

I would prefer the harder, but more safe way - if it is a string, it can be parsed:

//test dub
pageTracker = {
   _trackpageview: function(path) {alert(path)}
}

var str = "pageTracker._trackpageview('/url/page1.page')";

//get param
var urlpathregex = /\('([a-z0-9\-._~%!$&'()*+,;=:@\/]+)'\)/;
var param = urlpathregex.exec(str)[1];

//do some stuff/validation with param
[...]

//get object and function name
var funcregex = /([a-zA-Z0-9_]+)?\.?([a-zA-Z0-9_]+)(?=\()/;
var match = funcregex.exec(str);
var obj, func;
obj = match[1];
func = match[2];

//invoke
window[obj][func](param);

This is just an example, and not copy&paste ready code :) Because to begin with - if you get dynamically "pageTracker._trackpageview('/url/page1.page')" as a string, there is some code smell here already.

c64ification