3

My object has a call back:

var MyObject = {
CallBack: "function (whichSubMenuIsClicked, subMenuObjectTag) { self.doStuff(whichSubMenuIsClicked.SubMenuItem, whichSubMenuIsClicked.HeaderColumnName, whichSubMenuIsClicked.DivIdentifier);}",
}

The callback is a string. Now I need to execute it using MyObject.CallBack(param1, param2) How can this be done using jquery or javascript. The self in this case is the original widget calling another widget. Thus the call back is on the original widget.

chugh97
  • 9,602
  • 25
  • 89
  • 136
  • 1
    WTH would you write a function as a string if it shell be used as a function? – Bergi Nov 23 '12 at 14:13
  • 1
    In case not all the answers are clear, **you should not be doing this**. If you are receiving a function in JSON and therefore it needs to be a string, then **you shouldn't be receiving a function in JSON**. This approach needs to be reconsidered. It is inefficient and, as with any use of `eval`, insecure. – zetlen Nov 23 '12 at 14:19
  • @zetlen: It is only insecure when the source of the string can't be trusted - as with every script. Also have a look at [When is eval() not evil?](http://stackoverflow.com/q/197769/1048572) – Bergi Nov 23 '12 at 14:35
  • @Bergi you are absolutely right. Opening up a new execution context has its own security problems, but they are edge cases compared to the overall problems with running any untrusted code. – zetlen Nov 23 '12 at 15:38
  • @zetlen: You are receiving all/many functions as string: downloading them as .js file by a browser request. The key here is: can the source trusted or not. – g.pickardou Jun 01 '15 at 06:10

4 Answers4

3

Just don't have the function as a string.

Have the function as a function:

var MyObject = {
   CallBack: function (whichSubMenuIsClicked, subMenuObjectTag) {
                  self.doStuff(whichSubMenuIsClicked.SubMenuItem, whichSubMenuIsClicked.HeaderColumnName, whichSubMenuIsClicked.DivIdentifier);
             }
}
Curtis
  • 101,612
  • 66
  • 270
  • 352
1

Use the Function constructor, which accepts a list of parameter names followed by the function body:

var MyObject = {
    CallBack: "self.doStuff(whichSubMenuIsClicked.SubMenuItem, whichSubMenuIsClicked.HeaderColumnName, whichSubMenuIsClicked.DivIdentifier)",
};

var myfunc = new Function("whichSubMenuIsClicked", "subMenuObjectTag", MyObject.CallBack);
Asad Saeeduddin
  • 46,193
  • 6
  • 90
  • 139
0

You should write the function as a function, as @Curt demonstrated. Only if you really have no other choice than getting it as a string (e.g. from user input), you would first need to parse it to executable code which you then could call. The way to do so is eval. A problem will become the reference self, which is not a variable inside your function and would be assumed global. Yet, you can use a with statement to work around that:

var MyObject = {
    CallBack: "function (whichSubMenuIsClicked, subMenuObjectTag) { self.doStuff(whichSubMenuIsClicked.SubMenuItem, whichSubMenuIsClicked.HeaderColumnName, whichSubMenuIsClicked.DivIdentifier);}",
};
var widget = {doStuff: console.log};
var fn;
with( {self: widget} ) {
    fn = eval( MyObject.CallBack );
}
fn({SubMenuItem: "…", HeaderColumnName: "…", DivIdentifier: "…"});
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • You don't need eval, the `Function` constructor is purpose built for this. – Asad Saeeduddin Nov 23 '12 at 14:26
  • @Asad: Is it? Where is the difference? Also, the OP already has a full function string, and not a parameter list + function body code. Also, the `Function` constructor does not seem to be able to handle the `self` variable. – Bergi Nov 23 '12 at 14:29
  • The difference is that the Function constructor will never execute any statements passed to to it, whereas the `eval` function would execute any malicious statements sneaked in. This is pretty much the entire point behind the hubbub over the use of `eval`. I'm not sure what you mean by "handling the `self` variable". – Asad Saeeduddin Nov 23 '12 at 14:34
  • Of course `Function` does not execute any line of code - only you execute the resulting function. And malicious statements could be "sneaked" into a function body as well, there's no difference. – Bergi Nov 23 '12 at 14:38
  • Here's the difference: `eval('function(){};alert("LOL")')` vs. `new Function('//note that you can't sneak in code that will be immediately executed')` – Asad Saeeduddin Nov 23 '12 at 14:40
  • The `myfunc` your code generates references a `self` variable - which seems to be implied as global there. With `eval` and `with` you can assign a local variable. Try my function. – Bergi Nov 23 '12 at 14:44
  • @Asad: Ouch. Of course you would execute that function, otherwise you wouldn't need to generate it. `var myfunc = new Function('alert("LOL!");'); myfunc();` – Bergi Nov 23 '12 at 14:47
  • Yes, but I'm not talking about what the callback contains. My point is that it will always return a function, and not unexpectedly execute other code. If you have a callback that alerts `"LOL"` on loop, so be it, this is no different from property assigning `CallBack: function(){while(true){alert("LOL");}}`. We're not discussing the merits of what is in the function itself, we're talking about the ways of constructing it. At least `Function` follows a contract, and doesn't arbitrarily execute the code passed in. – Asad Saeeduddin Nov 23 '12 at 14:54
  • Sure, that's true. So if malicious code were injected, just the point of the unexpected execution would differ. However, I think `eval` is suited better for the OP's current problem (we still don't know the actual task) as it allows handling of variable scope and the OP already has a full `"function(){…}"` string which does not need to be parsed before. – Bergi Nov 23 '12 at 15:05
-2

Very bad approach but You can do it by eval()

var MyObject = { CallBack: "AName = function(param1, param2) { alert(param1 + param2); }", }

eval(MyObject.CallBack+"(1,2)"); 

Demo

Starx
  • 77,474
  • 47
  • 185
  • 261