任意の数のパラメーターを持つ関数をサポートする必要がある場合にのみ、eval/Functionルートをたどる必要があります。妥当な上限を設定できる場合(私の例は5)、次のように実行できます。
var wrapFunction = function( func, code, where ){
var f;
switch ( where ) {
case 'after':
f = function(t,a,r){ r = func.apply(t,a); code.apply(t,a); return r; }
break;
case 'around':
f = function(t,a){ return code.call(t,func,a); }
break;
default:
case 'before':
f = function(t,a){ code.apply(t,a); return func.apply(t,a); }
break;
}
switch ( func.length ) {
case 0: return function(){return f(this, arguments);}; break;
case 1: return function(a){return f(this, arguments);}; break;
case 2: return function(a,b){return f(this, arguments);}; break;
case 3: return function(a,b,c){return f(this, arguments);}; break;
case 4: return function(a,b,c,d){return f(this, arguments);}; break;
case 5: return function(a,b,c,d,e){return f(this, arguments);}; break;
default:
console.warn('Too many arguments to wrap successfully.');
break;
}
}
whereコードをラップするこの方法は、さまざまなスイッチを作成することによっても拡張できます。私が実装beforeしafterたのは、それらが自分のプロジェクトに最も役立つからです。そしてaround、それがLispを思い出させるからです。この設定を使用すると、ラッピング(var f)を外部コードに渡すこともできます。これにより、キーワードのシステムのようなプラグインを開発できます。whereつまり、wrapFunctionサポートされているものを簡単に拡張またはオーバーライドできます。
もちろん、コードの実際のラップ方法は好きなように変更できます。重要なのは、文字列の作成やへの受け渡しを気にせずに、999やAdrianLangと同様の手法を使用することnew Functionです。