0

我正在使用一个库(),它公开了一个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方法,以便在其所有递归调用之后,我可以执行我的代码。

4

2 回答 2

2

我仍然会使用一个简单的标志来确定我是否在递归中。

//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是一个标志,特定于这个单一的实现。也许您想将此代码包装在一个块或 iife 中,以确保无法从您的克隆方法外部访问这些变量。


您能否向我指出有关您正在谈论的优化的更多信息。我应该谷歌什么?

你会在 google 上找到关于v8 优化的大部分内容,但大多数现代浏览器都做类似的事情。我刚刚搜索了一下,发现了这篇文章Performance Tips for JavaScript in V8。它有点老了,但我认为这是开始了解 JS 引擎对代码进行哪些优化以使其更快的好点。

但正如它提到的文章,不要在(毫无意义的)优化中迷失自我。

于 2018-02-10T19:13:55.610 回答
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;
}
于 2018-02-10T19:51:03.363 回答