2

Possible Duplicate:
Why is using the JavaScript eval function a bad idea?

So I have read through MANY different methods on calling a function from a string, using window[](); and also eval();. I am wondering if for my situation (That is below) what method is exactly the right way to go ahead with, and if so, explain why. Also explain why eval(); isn't exactly a good option, a lot of people say security, but why would security be an issue if you can get any browser plugin that enables you to change the script on that page? (example: firebug for firefox)

My current code:

funcOne(target).funcTwo(x, y, z);

How would call this using the recommended window[](); way? And why can't I use this?:

eval('funcOne(target).funcTwo(x, y, z)');

I don't want your annoyance of this question being asked many times, because I cannot currently think of a way to call a, as a call it, double function.

Thanks in advance!

Community
  • 1
  • 1
pathurs
  • 643
  • 1
  • 5
  • 20
  • So you are trying to build a Firebug-like command line? Please give a little more information. `eval` might be the right choice, depending on what you want to achieve. – user123444555621 Oct 21 '12 at 09:06
  • I don't see how you could get confused on the question enough to think I want to make a firebug-like command line, but What I meant was that I would like to call a function that is generated from information that is not known before runtime, so I save it and execute it, but how? – pathurs Oct 21 '12 at 09:18

1 Answers1

6

In Javascript the syntax a.b can be replaced with a["b"]. So in your case you can use

window["funcOne"](target)["funcTwo"](x, y, z);

where of course it makes sense only if you are using variables instead of "funcOne" and "funcTwo".

If everything is instead fixed but you simply want to delay execution you can use "thunking" with an anonymous closure with

x = function(){ return funcOne(target).funcTwo(x, y, z); };

and then you can evaluate with x() to get the desired result later.

The last example will work correctly even if the variables target and x, y and z are local to the enclosing scope because the thunking closure will "capture" them.

You should however pay attention to the fact that in Javascript the only way to create a new scope is to use a function (a block surrounded with { and } is NOT a scope like happens in C++ and other languages).

If you need to create several closures in a loop this can bite back and is a source of a quite common mistake...

for (var i=0; i<options.length; i++)
{
    var menu_item = document.createElement("div");
    menu_item.textContent = "Option " + i;
    menu_item.onclick = function () {
        // Warning this will NOT work. All divs will
        // alert using the same number!
        alert("Option " + i + " selected");
    }
    menu.appendChild(menu_item);
}

here I used a closure for the onclick event on the div, but this is not going to work because all those functions will use the very same i variable. Because in Javascript the only way to create a scope is using a function the solution is:

for (var i=0; i<options.length; i++)
{
    var menu_item = document.createElement("div");
    menu_item.textContent = "Option " + i;
    (function(i){
         menu_item.onclick = function () {
             alert("Option " + i + " selected");
         };
     })(i); // Pass current `i` as parameter
    menu.appendChild(menu_item);
}

This way the variable i inside the onclick handler will be different for each closure.

This pattern of creating a function just to call it immediately is often used in Javascript when you need to create many independent closures so it's better to know and understand it.

6502
  • 112,025
  • 15
  • 165
  • 265
  • How would I achieve doing your second example with x() when all varaibles, target, x, y and z are scoped and I need to call it at any time while not within the same scope? – pathurs Oct 21 '12 at 08:59
  • @pathurs: It would work because the thunk will "capture" the local variables. If however you need to create many thunks it's important to understand that what is captured is the **variable** and not the **value of the variable** and often the mistake is to create many closures unintentionally sharing the same variables. See the extended explanation... – 6502 Oct 21 '12 at 12:57
  • Accepted and +1 due to detail of answer and multiple examples to give the best answer – pathurs Oct 25 '12 at 12:14