在仔细阅读每篇文章/评论后,我认为 OP 正在寻找[javascript]
和[method-modification]
. 并立即回答 OP 关于术语的问题,更改 JavaScript 中的封闭功能与面向方面的编程无关,除非声称是AO的实现至少为Aspect、Advice和Pointcut提供抽象和代码重用级别。
正如Scott Sauyet已经评论
过的那样,其他所有事情都可以通过(手动)将功能相互包装来完成。再说一次,我不会走那么远并将其称为function-composition。为了符合条件,至少应该有一些工具集,因为它们已经存在于各种实现compose
和/或curry
方法/模式中。
对于 OP 将要实现的目标,有一大堆before
, after
around
/wrap
解决方案,不幸的是提到AO(P),并且在很多情况下没有考虑上下文或者target
这是必不可少的,并且也被 OP 要求.
我提供的示例使用Function.around
. 由于bind
JavaScript
已经 具有标准化
的 .
Function.prototype
_ _
_
before
after
around
afterThrowing
afterFinally
将支持以下示例的代码库:
(function (Function) {
var
isFunction = function (type) {
return (
(typeof type == "function")
&& (typeof type.call == "function")
&& (typeof type.apply == "function")
);
},
getSanitizedTarget = function (target) {
return ((target != null) && target) || null;
}
;
Function.prototype.around = function (handler, target) { // [around]
target = getSanitizedTarget(target);
var proceed = this;
return (isFunction(handler) && isFunction(proceed) && function () {
return handler.call(target, proceed, handler, arguments);
}) || proceed;
};
}(Function));
示例代码,通过在它之前和之后额外提供的行为来改变给定的封闭函数,并提供它的上下文。
var loggingDelegate = function () { // closed code that can not be changed for any reason.
this.log.apply(this, arguments);
};
loggingDelegate.call(console, "log", "some", "arguments");
var interceptedLoggingDelegate = loggingDelegate.around(function (proceed, interceptor, args) {
// everything that needs to be done before proceeding with the intercepted functionality.
// [this] in this example refers to [console], the second argument of the [around] modifier.
this.log("proceed:", proceed); // the original functionality - here [loggingDelegate].
this.log("interceptor:", interceptor); // the modifying functionality - [around]s 1st argument.
this.log("args:", args); // the arguments that get passed around.
proceed.apply(this, args);
// or:
//return proceed.apply(this, args);
// or:
//var result = proceed.apply(this, args);
// everything that still needs to be done after invoking the intercepted functionality.
// if necessary:
//return result;
}, console); // [console] has to be provided as target to the modified [loggingDelegate].
interceptedLoggingDelegate("intercept", "and", "log", "some", "arguments");