在Javascript / jQuery中包装函数
如果我有一个任意函数myFunc
,那么我的目标是用一个在执行代码之前和之后运行代码的包装调用替换这个函数,例如
// note: psuedo-javascript var beforeExecute = function() { ... } var afterExecute = function() { ... } myFunc = wrap(myFunc, beforeExecute, afterExecute);
但是,我没有所需的wrap
函数的实现。 这样的jQuery中是否存在任何东西(我已经通过文档很好看了但看不到任何东西)? 或者有人知道这个的一个很好的实现,因为我怀疑有一堆边缘情况,如果我自己尝试写,我会想念?
(顺便说一下 – 之所以这样做是为了做一些function的自动检测,因为我们在Javascript剖析器等不可用的封闭设备上做了很多工作。如果有比这更好的方法那么我会很感激这些方面的答案太。)
这是一个wrap
函数,它将使用完全相同的参数调用before
和after
函数,如果提供,则this
调用相同的值:
var wrap = function (functionToWrap, before, after, thisObject) { return function () { var args = Array.prototype.slice.call(arguments), result; if (before) before.apply(thisObject || this, args); result = functionToWrap.apply(thisObject || this, args); if (after) after.apply(thisObject || this, args); return result; }; }; myFunc = wrap(myFunc, beforeExecute, afterExecute);
接受的实现不提供有条件地调用包装(原始)函数的选项。
这是一个更好的方法来包装和解包方法:
/* Replaces sMethodName method of oContext with a function which calls the wrapper with it's list of parameters prepended by a reference to wrapped (original) function. This provides convenience of allowing conditional calls of the original function within the wrapper, unlike a common implementation that supplies "before" and "after" cross cutting concerns as two separate methods. wrap() stores a reference to original (unwrapped) function for subsequent unwrap() calls. Example: ========================================= var o = { test: function(sText) { return sText; } } wrap('test', o, function(fOriginal, sText) { return 'before ' + fOriginal(sText) + ' after'; }); o.test('mytext') // returns: "before mytext after" unwrap('test', o); o.test('mytext') // returns: "mytext" ========================================= */ function wrap(sMethodName, oContext, fWrapper, oWrapperContext) { var fOriginal = oContext[sMethodName]; oContext[sMethodName] = function () { var a = Array.prototype.slice.call(arguments); a.unshift(fOriginal.bind(oContext)); return fWrapper.apply(oWrapperContext || oContext, a); }; oContext[sMethodName].unwrapped = fOriginal; }; /* Reverts method sMethodName of oContext to reference original function, the way it was before wrap() call */ function unwrap(sMethodName, oContext) { if (typeof oContext[sMethodName] == 'function') { oContext[sMethodName] = oContext[sMethodName].unwrapped; } };
你可以这样做:
var wrap = function(func, pre, post) { return function() { var callee = arguments.callee; var args = arguments; pre(); func.apply(callee, args); post(); }; };
这将允许您这样做:
var someFunc = function(arg1, arg2) { console.log(arg1); console.log(arg2); }; someFunc = wrap( someFunc, function() { console.log("pre"); }, function() { console.log("post"); }); someFunc("Hello", 27);
这给了我Firebug中的输出:
pre Hello 27 post
以这种方式包装时的重要部分是将参数从新函数传递回原始函数。
这是我将使用的示例
也许我错了,但我认为你可以直接创建一个匿名函数并将其分配给myFunc:
myFunc = function(){ BeforeFunction(); myFunc的(); AfterFunction(); }
通过这种方式,您可以控制每个函数的参数。