2

I'm trying to write a JavaScript function that gets some variables and returns a function that contains their values without taking them as parameters or referencing them.

A simple example:

function foo(a,b) {
    return function(x) {
        //doing something with values of a and b, for example:
        return a*x + b;
    }
}

So if I do:

var c = foo(2,3);
var d = foo(4,5);

c and d will look like:

c:  function(x) {
    return 2*x + 3;
}
d: function(x) {
    return 4*x + 5;
}

I want foo() to replace the variables a,b with their values before returning the new function. So c and d dont need to refer to some vars outside themselves.

I work with CasperJS and try to dynamically create functions to be executed by casper.evaluate() which sandboxes the executed functions. This is why it wouldn't work the way described in the example.

Any ideas how to solve this? Thanks alot!

EDIT:

Why do I need this? I try to write an abstract crawler with CasperJS. So there is a "main"-function that accesses an object-variable (var site = {...}) containing multiple functions which casper.evaluate() takes as arguments, one by one. These functions are executed sandboxed on the opened webpage so they cannot access any variables outside the webpage. They can do very different things but mostly they look for one kind of tag that contains a link/image/reference, replaces this reference and returns all of them in a list. This function could be used for links, images, css-files, js-files etc. and only needed a different selector, attribute-name (and maybe 1-2 other variables) for each of them. I cannot give them as arguments to this function, because every function might need a different number of arguments then and the casper.evaluate(site[i]['method']) call does not know about them. It calls the function without any arguments. That's why I thought implementing a function that generates these functions would be the nicest way. But apparently this doesn't work the way I planned.

Of course I could just copy this function and replace the few variables. But this would create a lot of redundant code and bring all of its disadvantages.

Another idea: the functions are called with a specific number of arguments which are stored inside the same object: casper.evaluate(site[i]['method'],site[i]['arg0'],site[i]['arg1']...)

I think this should work but is not very nice because every function must have this specific number of arguments even if it doesn't need one. And it only works as long as no function needs more arguments.

3
  • 2
    To rephrase: You want to convert a function to a standalone string, inlining references to closured variables. Commented Jun 18, 2015 at 19:25
  • This sounds like an XY Problem. Commented Jun 18, 2015 at 19:32
  • @zzzzBov It surely has potential to be an XY problem. I've run into this a couple of times and always found a workaround. But those workarounds are ugly (duplicating much code which is bad for code health or bootstrapping code in the page context which reduces interactability). I too hope there is a clean solution to this. Commented Jun 18, 2015 at 20:37

2 Answers 2

1

Maybe this could work for you. This is your example but allowing perform a function with any number of arguments.

function foo() {
    var func = function() {
        //doing something with arguments of the original function:
        return arguments;
    };
    var allArgs = Array.prototype.slice.call(arguments); // 1
    allArgs.unshift(null); // 2
    return Function.prototype.bind.apply(func, allArgs); // 3
}
  1. get all arguments of the outher function and covert them to array
  2. put null at the beginning of the arguments list
  3. return copy of a inner function which has bound all arguments from outher function. The null which we put a the beginning of allArgs array is used as this argument for bind function.

Example usage:

var c = foo(1,2,3,4,5,6);
c(7); // returns: [1, 2, 3, 4, 5, 6, 7]
Sign up to request clarification or add additional context in comments.

Comments

0
function foo(a,b)
{
    return new Function("x", "return " + a + "*x+" + b);
}

1 Comment

For 1 line functions that might be okay but when 20 lines of code have to be passed as string, that's not a very nice way. But I guess there's no other ways?

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.