Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if JavaScript function returns without executing it?

I have a given function that takes, among other arguments, two optional arguments which may be functions. Both need to be optional, one will be a function, and one will either be a boolean or a function that returns a boolean.

// Obj.func(variable, String[, Object][, Boolean||Function][, Function]);
Obj.func = function(other, assorted, args, BoolOrFunc, SecondFunc) {
    // execution
};

Obj.func(
    [
        'some',
         'data'
    ],
    'of varying types',
    {
        and: 'some optional arguments'
    },
    function() {
        if(some condition) {
            return true;
        }
        return false;
    },
    function() {
       // do things without returning
    }
);

It is my desire that both functions (and several of the other arguments, if it matters) be optional, which means I have code in the function to determine which arguments the user intended to use.

Unfortunately, as both may be functions, and may be specified directly in the function call, I cannot simply use typeof or instanceof conditionals. However, since the first function, if it exists, will always return a boolean (and the second function will not return at all), one idea I had would be to check its return value:

if(typeof BoolOrFunc === 'boolean'
   || (typeof BoolOrFunc === 'function' && typeof BoolOrFunc() === 'boolean')) {
    // BoolOrFunc is either a boolean or a function that returns a boolean.
    // Handle it as the intended argument.
} else {
    // Otherwise, assume value passed as BoolOrFunc is actually SecondFunc,
    // and BoolOrFunc is undefined.
}

This works in principle; however, running typeof BoolOrFunc() executes the function, which causes a problem if the function does more than just return a boolean: that is, if the function passed as BoolOrFunc is actually meant to be SecondFunc. SecondFunc, in this case, is something of a callback function, and may perform actions, including DOM modifications, that I don't want to execute immediately.

For this reason, my question is: Is there a way to check if a function returns without executing it?

One thing I had considered was to call BoolOrFunc.toString(), then perform a Regular Expression search for the return value, something along the lines of…

if(typeof BoolOrFunc === 'boolean'
   || (typeof BoolOrFunc === 'function'
       && BoolOrFunc.toString().search(/return (true|false);/) !== -1)) {
    // BoolOrFunc is either a boolean or contains a return string with a boolean.
    // Handle it as the intended argument.
}

Note that the above code may not work as written: I've not actually built a test case for it, because, well, it seems exceptionally inefficient and potentially unreliable, and I figured someone here might have a more elegant solution to my quandary. That having been said, I figured I'd include it for discussion purposes.

like image 320
Meshaal Avatar asked Sep 09 '14 07:09

Meshaal


1 Answers

Meshaal made a prediction in the question:

"... one will either be a boolean or a function that returns a boolean."
"... first function, if it exists, will always return a boolean."

With this prediction the function is not a Turing Machine, because we know that it returns something. Surely it can't be done with a simple RegExp: just return !0 would break the example.

But if you parse the result of function.toString() with a parser being intelligent enough to find all possible return points, the problem should principally be solvable.

like image 193
Martin Ernst Avatar answered Sep 21 '22 20:09

Martin Ernst