如何修补递归函数

时间:2018-02-10 18:58:44

标签: javascript monkeypatching playcanvas

我正在使用一个库()来公开一个函数clone(),该函数以递归方式为层次结构中的所有节点调用。

如果我修补函数以执行一些额外的代码,这将被执行多次。

相反,我需要在整个递归调用结束时执行我的代码,但我找不到办法。

pc.Entity.prototype.clone = function() {
    ... some code
    // then for each child it calls itself
}

如果我尝试这种方式,我会多次执行“我的东西”。

pc.Entity.prototype.cloneOriginal = pc.Entity.prototype.clone;

pc.Entity.prototype.clone = function() {
    var c = this.cloneOriginal();
    // do my stuff
    return c;
}

我需要“覆盖”clone方法,以便在完成所有递归调用之后,我可以执行我的代码。

2 个答案:

答案 0 :(得分:2)

您可以通过在启动之前暂时恢复原始功能来实现此目的。完成后,再次设置陷阱,并执行后期处理:

const orig_clone = pc.Entity.prototype.clone; // Save original clone
// Set trap:
pc.Entity.prototype.clone = function patched_clone(...args) {
    pc.Entity.prototype.clone = orig_clone; // Restore original function
    let result = this.clone(...args); // Execute it
    // All is done, including recursion. 
    pc.Entity.prototype.clone = patched_clone; // Set trap again
    // Your code comes here
    console.log('post processing');
    return result;
}

答案 1 :(得分:1)

我仍然带着一个简单的旗帜来判断我是否在递归中。

//no need to store that function on the prototype itself
const cloneOriginal = pc.Entity.prototype.clone;

let inRecursion = false;
pc.Entity.prototype.clone = function() {
    //just pass through the call to the original function.
    if(inRecursion)
        return cloneOriginal.call(this);

    inRecursion = true;
    var c = cloneOriginal.call(this);
    inRecursion = false;

    // do my stuff
    return c;
}

inRecursion是一个标志,专门用于此单个实现。也许您希望将此代码包装在块或生命中,以确保无法从克隆方法外部访问变量。

  你可以给我一些关于你所说的优化的更多信息吗?我该怎么去谷歌?

您最常在谷歌上找到关于 v8优化的内容,但大多数现代浏览器都会做类似的事情。我只是用Google搜索并发现了这篇文章Performance Tips for JavaScript in V8。它有点老了,但我认为开始理解JS引擎对你的代码做的优化以使其更快化是一个很好的观点。

但正如它提到的那篇文章,不要在(毫无意义的)优化中放松自己。