在Javascript/jQuery中包装函数
如果我有一个任意函数在Javascript/jQuery中包装函数,javascript,jquery,instrumentation,Javascript,Jquery,Instrumentation,如果我有一个任意函数myFunc,我要做的就是用一个在执行前后运行代码的包装调用来替换这个函数,例如 // note: psuedo-javascript var beforeExecute = function() { ... } var afterExecute = function() { ... } myFunc = wrap(myFunc, beforeExecute, afterExecute); 但是,我没有所需的wrap函数的实现。jQuery中是否已经存在这样的东西(我已
myFunc
,我要做的就是用一个在执行前后运行代码的包装调用来替换这个函数,例如
// note: psuedo-javascript
var beforeExecute = function() { ... }
var afterExecute = function() { ... }
myFunc = wrap(myFunc, beforeExecute, afterExecute);
但是,我没有所需的wrap
函数的实现。jQuery中是否已经存在这样的东西(我已经仔细查看了文档,但什么都看不到)?或者,是否有人知道这是一个很好的实现,因为我怀疑如果我尝试自己编写它,会错过很多边缘案例
(顺便说一句,这样做的原因是要对函数进行一些自动检测,因为我们在没有Javascript探查器等的封闭设备上做了大量工作。如果有更好的方法,我也希望您能回答这些问题。)您可以这样做:
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
以这种方式包装时,最重要的部分是将参数从新函数传递回原始函数。这就是我将使用的示例
<script type="text/javascript">
var before = function(){alert("before")};
var after = function(param){alert(param)};
var wrap = function(func, wrap_before, wrap_after){
wrap_before.call();
func.call();
wrap_after.call();
};
wrap(function(){alert("in the middle");},before,function(){after("after")});
</script>
var before=function(){alert(“before”)};
var after=函数(param){alert(param)};
var wrap=函数(func,在前换行,在后换行){
在.call()之前包装_;
函数调用();
在.call()之后包装_;
};
换行(function(){alert(“中间”);},在前面,function(){after(“后面”)});
也许我错了,但我认为您可以直接创建一个匿名函数并将其分配给myFunc:
myFunc = function(){
BeforeFunction();
myFunc();
AfterFunction();
}
myFunc=函数(){
BeforeFunction();
myFunc();
后功能();
}
通过这种方式,您可以控制每个函数的参数。这里有一个
wrap
函数,它将使用完全相同的参数调用之前的和之后的函数,如果提供了此的相同值:
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;
}
};
它还显示了如何参数化使用wrap运行的函数。如果您使用参数调用函数,则可能会在包装自身之前执行whey。如果正在包装的函数具有参数…,则这似乎不起作用?这就是为什么您应该在function(){…}调用中包装参数函数的原因。否则,您将启动函数以获得其结果。我将勾选这一个作为正确答案,因为我认为这是问题的最完整解决方案,并处理具有任意数量参数的函数。干杯我希望jQuery中可能有一个标准的库函数用于此,但我始终可以将其添加到我们的扩展中。我做了一个小小的编辑,以便在创建包装时没有指定thisObject
时使用“常规”this
对象。为什么要将被调用方作为this
传递?