In terms of closure, if only account for functions that return another function as shown in the following examples. How do we programmatically determine the depth of this closure in runtime?
Let's say this function F
has the depth of 2:
function F(a){ // 1
return function G(b){ // 2
return 'something';
}
}
This function 'H' has the depth of 3.
function H(a){ // 1
return function(b){ //2
return function(c){} //3
}
}
So far I have made some simple script to determine the depth of closure by iteratively checks the return type of a function until it returns other type than the function. But my script only works in the case where each nested function requires no argument. See the following code:
function F(){
return function(){
return function(){
return 1;
}
}
}
function depth(f){
var n = 1;
var ret = f();
while (typeof(ret)=='function'){
ret = ret();
n++;
}
return n;
}
The simple function depth
above correctly determines the depth of F
which is 3. However, in some real-world cases such as closures which take function as argument and invoke it, my function depth
cannot deal with.
function F2(a,f){
return function(g){
return f(a) + g(a); // This will break my depth function
}
}
*My question : Is there any way to determine how deep my closure is more efficiently? Especially in some cases mentioned above (closures which take function as argument and invoke it). Generic way which can dynamically cope with closures which may or may not take some functions as arguments will be most appreciated.
P.S. Let me narrow down the scopes as follows.
- Only pure nested functions are taken into account.
- Each layer of nested function always returns the same type.
- The depth of the function is constant.
- Neither one of the nested functions is recursive.
Here is another approach. This works at runtime by observing how the code behaves.
My function
Reflector
is the special sauce in this case.See https://jsfiddle.net/rffv34oz/8/ for running the example.
The function
Reflector
does four things:1. It "instruments" a function with a hook (
fh
) by returning the hook instead of the original function. The effect is that the hook is called before that instrumented function is called.2. When the instrumented function is called, it forwards the call - it calls the original function. And remains ready for capturing the function result.
3. When the function returns, it inspects the result. If the result is also a function, it stores new maximum depth.
4. Also, when the returned result was a function, the hook also instruments the returned function, so that step (1) is again applied for the new returned function.