5

I've done a bit of googling round but this particular problem is a little too similar to the "how do i evaluate function names from strings" so I'm having trouble finding a solution, I want to convert a string into a function so say i had something like:

for (var i = 0; i < someNumber ; i++) {
    var foo = "function() { someObject.someOtherFunctionCall(" + i + ") }";
    someArray[i] = foo;
}

how would I typecast foo so I could call

someArray[0]();

I need the value baked into the function, any ideas?

EDIT: I just substituted "value" for "i" apologies for the confusion

UPDATE:

Ok, I have accepted icktoofay answer because it works, to answer most of your questions and concerns; I have tried most of the methods suggested all of which either didn't pass the variable to the calling locations scope or required closures that persisted with the last functions variable value, unfortunately I don't have control over the rest of the code so I cant make modifications to the location the function eventually gets called.

This is probably a temporary solution; I'm aware of how ugly parsing strings for functions is. as far as browser compatibility goes this will only ever run in one environment, so I think we're pretty safe there.

Anyway, thanks again for the prompt answers and discussion.

2
  • 5
    I'd really like to know why you want to do this, as it seems like a Bad Idea(tm). Commented Nov 24, 2011 at 22:22
  • 1
    I'm really curious as to why you have functions defined as strings? Commented Nov 24, 2011 at 22:22

5 Answers 5

5

If you just want an array of functions that simply call a method, it's much more simple:

for(var i=0; i<someNumber; i++) {
    someArray.push(someObject.someOtherFunctionCall.bind(someObject, i));
}

Note that this requires Function.bind, which may not be available in older browsers. If you need support for older browsers, you can shim it or use this version:

for(var i=0; i<someNumber; i++) {
    someArray.push(function(i) {
        return function() {
            return someObject.someOtherFunctionCall(i);
        };
    }(i));
}

Edit: Here is the old answer, which should also work, but is less elegant:

for (var i = 0; i < someNumber ; i++) {
    var foo = new Function("someObject", "return function() { someObject.someOtherFunctionCall(" + value + ") }")(someObject);
    someArray[i] = foo;
}
Sign up to request clarification or add additional context in comments.

Comments

2

Try:

var foo = function() { someObject.someOtherFunctionCall(value ) };
someArray[i] = foo; 

or

if foo is not a global variable, you can do this to pass the value:

 var foo = (function(value) { return function() { someObject.someOtherFunctionCall(value ) } }) ( value );  

1 Comment

I tried this, the problem with this in a loop is, the closures "value" will allays be set to the last iteration of the value passed to it, making all the calls have the value of 99
1

you can use the inner part between the brackets only and call them via eval() function.

here is the description: http://www.w3schools.com/jsref/jsref_eval.asp

here is an example:

for (var i = 0; i < someNumber ; i++) {
    var foo = "someObject.someOtherFunctionCall(" + value + ");";
    someArray[i] = foo;
}

eval(someArray[0]);

Comments

1

Even if you get that working, it is rather insecure if the value is not sanitized input. I would just use an anonymous function (no strings), like this:

var foo = function() { someObject.someOtherFunctionCall(value) };

Because of the scope in JS, value will be available to foo at a later time, unless you change value after that line, then it will read the altered value.

EDIT: When I looked closely at the question, I realized this doesn't work. Please give me some time to reconsider my answer.

UPDATE: If you really want to do this, consider the other answers.

(JS gods will cry, though…)

Comments

1

Just give it its own scope,

for (var i = 0; i < someNumber ; i++) {
    someArray[i] = (function(idx){
        return function() { someObject.someOtherFunctionCall(idx); };
    })(i)        
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.