如何猴子修补递归函数
How to monkey patch a recursive function
我正在使用一个库(playcanvas) that exposes a function clone()
对层次结构中的所有节点递归调用。
如果我猴子修补函数以执行一些额外的代码,这将被执行多次。
相反,我需要在整个递归调用结束时执行我的代码,但我找不到执行此操作的方法。
pc.Entity.prototype.clone = function() {
... some code
// then for each child it calls itself
}
如果我尝试这种方式,我会 "my stuff" 执行多次。
pc.Entity.prototype.cloneOriginal = pc.Entity.prototype.clone;
pc.Entity.prototype.clone = function() {
var c = this.cloneOriginal();
// do my stuff
return c;
}
我需要 "override" clone
方法,以便在所有递归调用之后,我可以执行我的代码。
我仍然会使用一个简单的标志来确定我是否在递归中。
//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 中,以确保无法从您的克隆方法外部访问这些变量。
could you point me to some more info about the optimization you are speaking about. What should I google?
您会在 google 上找到关于 v8 优化 的大部分信息,但大多数现代浏览器都做类似的事情。我刚刚 googled 看到了这篇文章 Performance Tips for JavaScript in V8。它有点旧,但我认为开始了解 JS 引擎对您的代码所做的优化以使其更快是一个很好的起点。
但是正如文章中提到的那样,不要在 (毫无意义) 优化中放松自己。
您可以通过在启动之前临时恢复原始功能来实现。完成后,您再次设置陷阱,并执行 post 处理:
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;
}
我正在使用一个库(playcanvas) that exposes a function clone()
对层次结构中的所有节点递归调用。
如果我猴子修补函数以执行一些额外的代码,这将被执行多次。
相反,我需要在整个递归调用结束时执行我的代码,但我找不到执行此操作的方法。
pc.Entity.prototype.clone = function() {
... some code
// then for each child it calls itself
}
如果我尝试这种方式,我会 "my stuff" 执行多次。
pc.Entity.prototype.cloneOriginal = pc.Entity.prototype.clone;
pc.Entity.prototype.clone = function() {
var c = this.cloneOriginal();
// do my stuff
return c;
}
我需要 "override" clone
方法,以便在所有递归调用之后,我可以执行我的代码。
我仍然会使用一个简单的标志来确定我是否在递归中。
//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 中,以确保无法从您的克隆方法外部访问这些变量。
could you point me to some more info about the optimization you are speaking about. What should I google?
您会在 google 上找到关于 v8 优化 的大部分信息,但大多数现代浏览器都做类似的事情。我刚刚 googled 看到了这篇文章 Performance Tips for JavaScript in V8。它有点旧,但我认为开始了解 JS 引擎对您的代码所做的优化以使其更快是一个很好的起点。
但是正如文章中提到的那样,不要在 (毫无意义) 优化中放松自己。
您可以通过在启动之前临时恢复原始功能来实现。完成后,您再次设置陷阱,并执行 post 处理:
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;
}