JavaScript代码中的三明治模式
sandwich pattern in javascript code
如果问题的标题具有误导性,请道歉。实际上,我正在寻找与以下python代码等效的javascript:
## python code
def call_with_context(fn, *args):
## code to create context, e.g. profiling, db.connect, or drawing context store stack
fn(*args)
## code to close context
这实现了与python中的"with语句"类似的功能,后者实现了面向方面的范式。
所以我的问题是做这些事情的javascript方式是什么?我已经看到一些使用 Array.prototype.slice(arguments, 1) 的代码来做到这一点,但我不知道这是否是 javascript 中的常见模式,或者 javascript 中支持更好的模式(例如通过闭包),所以 ppl 并没有真正这样做。如果我使用了错误的关键字,请也纠正我,因为我真的不知道如何用比三明治更好的名称来指代我的问题。
EDT 1:如果有人能解释如何从包装器内部返回 fn(*args) 的结果,我将不胜感激call_with_context谢谢!
我认为更典型的JS方法可能是装饰函数。 因此,如果你想将你的函数包装在记录计时的东西中,你可以创建一个这样的函数(在我的头顶上):
var createTimer = function(fn) {
return function() {
var start = new Date();
var result = fn.apply(this, arguments);
console.log("Took " + (new Date() - start) + " ms.");
return result;
}
};
var test = function(a, b, c) {
return a * b + c;
}
test = createTimer(test);
console.log(test(3, 4, 5));
// Took 0 ms.
// 17
重点是你可能不会这样称呼这样的东西:
runTimerAround(test, 3, 4, 5);
虽然这也可以在 JS 中完成,但我相信它比直接覆盖函数更不常见。
听起来你想调用一个具有特定上下文的方法。
在 js 中,您通常会执行...
function someFunction( fn, context ) {
fn.call( context );
}
var Button = {
isClicked: false
};
someFunction(function () {
// this === Button
this.isClicked = true;
}, Button );
现在,fn
中的 this
关键字将表示传递到方法 someFunction
的上下文。这种模式经常发生。尤其是回调。
这是我经过一些搜索后的解决方案。希望对其他人有帮助。
function call_with_context(fn) {
// some beginning code
console.log('begin');
r = fn.apply(null, Array.prototype.slice.call(arguments, 1));
// some ending code
console.log('end');
return r;
}
像这样的东西
// javascript code
function call_with_context(fn) {
// code to create context, e.g. profiling, db.connect, or drawing context store stack
var r = fn.call(Array.prototype.slice.call( arguments, 1)); // remove first arg - fn
//code to close context
return r;
}
因此,您将能够执行此操作:
call_with_context(myfun,1,2,3);
最终会在通话中结束
myfun(1,2,3);
在仔细阅读了每篇帖子/评论后,我认为 OP 是寻找[javascript]
和[method-modification]
.并正确回答消除了OP关于术语的问题,改变了封闭的功能JavaScript 与面向方面的编程无关,除非声称是AO的实现提供了抽象和代码重用至少方面,建议和切入点的水平。
正如已经评论的那样作者:斯科特·索耶特,一切否则可以通过(手动)将功能相互包装来完成。这里同样,我不会走那么远,称之为函数组合。为了有资格,至少应该有一些工具集,因为它们已经存在于compose
和/或curry
方法/模式的各种实现中。
对于OP将要实现的目标,有一大堆before
,after
around
/wrap
解决方案,不幸的是,大多数都提到了AO(P),并且也提到了AO(P)许多案件没有考虑到背景或target
这是必要的和OP也要求
我提供的示例使用了Function.around
的原型实现。因为JavaScript已经具有标准化bind
,我坚信该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");
- Javascript,访问一个主要对象模块模式中的每个对象
- 是否有任何snippet或jQuery插件可以列出easylist.txt模式匹配的DOM中的所有元素
- 试图在引导模式内动态生成图表,得到offsetWidth错误
- 同位素库错误:未捕获错误无布局模式包装生产线8
- 在DOM中查找一个模式并替换它's的内容使用jquery
- 如何缩短MongoDB ObjectId并在Mongoose模式中使用它
- D3.js模式不适用于弧形或圆环图
- Webdriver.io pageObject模式-通过传递参数来定义元素选择器
- 模块模式和这个
- 带有let的JS/EECMAScript6私有字段的模式
- 我是否可以检测到javascript正在被卸载(作为调试模式)
- 执行动态模式弹出
- 注意:wp_enqueue_script调用不正确.在 Wordpress 调试模式下
- AngularJS ui路由器html5模式中断路由
- 包含圆括号的JavaScript Regex模式
- 显示模块模式在Knockout中设置模型的新实例
- Node.js使用Series函数(模式?)实现流控制时出现意外结果
- 使用模式格式化Number类型输入中的值
- Markdown模式代码镜像正在创建
- JavaScript代码中的三明治模式