编程语言
首页 > 编程语言> > javascript-如何有效地确定关闭的深度

javascript-如何有效地确定关闭的深度

作者:互联网

就闭包而言,仅考虑返回其他函数的函数,如以下示例所示.我们如何在运行时以编程方式确定此关闭的深度?

假设此函数F的深度为2:

function F(a){ // 1
    return function G(b){ // 2
        return 'something';
    }
}

函数“ H”的深度为3.

function H(a){ // 1
   return function(b){ //2
      return function(c){} //3
   }
}

到目前为止,我已经编写了一些简单的脚本来确定闭合的深度,方法是迭代检查函数的返回类型,直到它返回函数以外的其他类型.但是我的脚本仅在每个嵌套函数都不需要参数的情况下起作用.请参见以下代码:

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; 
}

上面的简单函数深度正确地确定了F的深度3.但是,在某些实际情况下,例如以函数为参数并调用它的闭包,我的函数深度无法处理.

function F2(a,f){
    return function(g){
        return f(a) + g(a); // This will break my depth function
   }
}

*我的问题:有什么方法可以确定我的封包更有效的深度吗?特别是在上述某些情况下(以函数为参数并调用它的闭包).可以动态地处理可以将某些函数作为参数或不将某些函数作为参数的闭包的通用方法将是最受赞赏的.

附言让我缩小范围如下.

>仅考虑纯嵌套函数.
>嵌套函数的每一层总是返回相同的类型.
>功能的深度是恒定的.
>嵌套函数之一都不是递归的.

解决方法:

这是另一种方法.通过观察代码的行为,这在运行时有效.
我的功能Reflector是这种情况下的特殊调味料.
运行示例请参见https://jsfiddle.net/rffv34oz/8/.

Reflector函数执行四件事:
1.它通过返回钩子而不是原始函数来“插入”带有钩子(fh)的函数.效果是在调用该检测函数之前先调用该钩子.
2.调用已检测的函数时,它将转发该调用-它将调用原始函数.并随时准备捕获功能结果.
3.函数返回时,将检查结果.如果结果也是一个函数,它将存储新的最大深度.
4.同样,当返回的结果是一个函数时,该钩子还会对返回的函数进行检测,因此将步骤(1)再次应用于新的返回的函数.

//Your function You want to USE and REFLECT on too.
function F(){ 
    //return 3;
    return function(){
        //return 2;
        return function(){
            return 1;
        }
   }
}

//Your function You want to USE and REFLECT on too.
function H(a){ // 1
    return function(b){ //2
        return function(c){ //3
            return a + b + c;   
        }
   }    
}

//this function is the machinery that knows how to USE the functions You want to measure. 
//But this function only USES them, but does no reflection.
function BlackboxF(f) { 

    var r1 = f();
    if (typeof r1 == "function")
    {
        var r2 = r1();
        if (typeof r2 == "function")
        {
            var r3 = r2();  

            return r3;
        }
        else 
        {
            return r2;   
        }
    }
    else 
    {
         return r1;   
    }

}

//this function is the machinery that knows how to USE the functions You want to measure. 
//But this function only USES them, but does no reflection.
function BlackboxH(f) { 

    var r1 = f(1);
    var r2 = r1(2);
    var r3 = r2(4);
    return r3;

}

var maxdepth = 1;

//This is the special agent for reflecting code as it runs
function Reflector(f, depth) { 

    if (!depth)
        depth = 1;

    //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.
    var fh = function()     
    {
        //2. When the instrumented function is called, it forwards the call - it calls 
        //the original function. And remains ready for capturing the function result.
        var r = f.apply(this, arguments);    

        //3. When the function returns, it inspects the result. 
        //If the result is also a function, it stores new maximum depth.
        if (typeof r == "function")
        {
            maxdepth = Math.max(maxdepth, depth + 1);

            //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.
            return Reflector(r, depth + 1);        
        }
        else 
        {
            return r;
        }
    };

    return fh;
}

if (false) //The simple case with no arguments
{
    var F2 = Reflector(F);
    var RF = BlackboxF(F2);

    document.getElementById("result").textContent = "Result: " + RF;
    document.getElementById("depth").textContent = "Depth: " + maxdepth;
}
else //A more complicated case with arguments
{
    var H2 = Reflector(H);
    var RH = BlackboxH(H2);

    document.getElementById("result").textContent = "Result: " + RH;
    document.getElementById("depth").textContent = "Depth: " + maxdepth;
}

标签:closures,javascript
来源: https://codeday.me/bug/20191120/2042032.html