Обтекание функции в Javascript/jQuery
Если у меня есть произвольная функция myFunc
, то я собираюсь сделать это, заменив эту функцию заверенным вызовом, который запускает код до и после его выполнения, например.
// note: psuedo-javascript
var beforeExecute = function() { ... }
var afterExecute = function() { ... }
myFunc = wrap(myFunc, beforeExecute, afterExecute);
Однако у меня нет реализации требуемой функции wrap
. Есть ли что-то, что уже существует в jQuery, как это (я хорошо просмотрел документы, но ничего не вижу)? Или кто-нибудь знает о хорошей реализации этого, потому что я подозреваю, что есть куча крайних случаев, которые я пропущу, если я попытаюсь написать это сам?
(BTW - причина этого заключается в том, чтобы сделать некоторые автоматические функции функций, потому что мы делаем много работы на закрытых устройствах, где Javascript-профилировщики и т.д. недоступны. Если есть лучший способ, чем это, тогда я буду благодарен за ответы по этим линиям тоже.)
Ответы
Ответ 1
Heres a 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);
Ответ 2
Принятая реализация не предоставляет возможность условно вызывать завернутую (оригинальную) функцию.
Вот лучший способ обернуть и развернуть метод:
/*
Replaces sMethodName method of oContext with a function which calls the wrapper
with it 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;
}
};
Ответ 3
Вы можете сделать что-то вроде:
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
Важная часть при переносе этого способа передаёт ваши аргументы из новой функции обратно в исходную функцию.
Ответ 4
Это пример, который я использовал бы
<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>
Ответ 5
Возможно, я ошибаюсь, но я думаю, что вы можете напрямую создать функцию анонима и назначить ее myFunc:
myFunc = function(){
BeforeFunction();
myFunc();
AfterFunction();
}
Таким образом вы можете управлять аргументами каждой функции.