问题描述
在Javascript和许多其他编程语言中,我们可能会将函数作为参数传递给其他函数。这是函数式编程中的一种常见做法。
我们知道包装器需要在其中放置一个断点,以查看其在堆栈跟踪中的位置,以更好地控制参数或在调用之前/之后添加逻辑。
还有其他客观原因不将展开函数作为参数传递吗?
myFunction1(x => myFunction2(x)) // wrapped
myFunction1(myFunction2) // unwrapped
解决方法
“应该”使用一种或另一种技术在SO中大部分是禁止的。
不过,我将回答一个相关的问题,关于何时可以使用该技术以及不能使用该技术以及可能存在的(不利)优势。
您始终可以写std::fstream dwrite;
dwrite >> /* ... */; // ok
dwrite << /* ... */; // ok
。您不能总是写foo (x => bar (x))
。在another Q & A中可以找到为什么的示例。根据我的经验,一个常见的例子是带有第二个参数的递归函数,该参数在初始调用中默认,并在后续调用中传递。通过简单引用foo (bar)
不能成功传递此函数,因为map
除了期望值之外还提供其他参数。
但这是不寻常的情况。如果您的函数没有默认参数,则在包装器中似乎没什么用。一个论点就是,如果要用map
代替foo (bar)
,为什么不更进一步,而使用foo (x => bar (x))
或foo (y => (x => bar (x)) (y))
。>
包装器可以工作,但是什么也没添加……除了,因为您指出它是挂断点的地方。
这对您来说可能是合理的情况。这些天,我在调试器上花费的时间并不多,但是当我这样做时,有时可能会临时添加这样的包装器。但是我之后将其删除。我发现干净的代码非常重要,不必要的包装程序只会使事情变得混乱。在代码审查中,我一直反对这种模式:
foo (z => (y => (x => bar (x)) (y)) (z))
我经常需要指出的地方可以写得更清楚:
const foo = (...args) => {
// do something with args
return new Promise ((resolve,reject) => {
bar (something).then(
(a) => {
resolve (a);
},(err) => {
reject (err);
}
);
});
}
然后我必须进一步指出,即使这样也可以更好地写为
const foo = (...args) => {
// do something with args
return new Promise ((resolve,reject) => {
bar (something) .then (resolve,reject);
});
}
重点是const foo = (...args) => {
// do something with args
return bar (something);
}
和resolve
周围的函数包装器很混乱。 reject
周围的Promise包装器也是如此。它不会损害结果,只会对性能产生很小的影响,但几乎无法平衡混乱情况。
(而且,我试图在这里避免发表意见,但实际上是不可能的。)
,您无需使用匿名函数包装函数即可将其分配为事件处理程序。如果函数应该获取事件对象,就可以了。
window.addEventListener('click',myFunction)
此外,用匿名函数包装该函数将阻止您删除事件处理程序,因为remove期望与添加的事件处理程序相同。
这将起作用:
window. removeEventListener('click',myFunction)
这不会:
window.removeEventListener('click',e => myFunction(e))
如果需要将更多参数传递给事件处理程序,则需要对其进行处理,并将返回的函数分配给变量,以便删除处理程序:
const createEventHandler = param => e => {}
const eventHandler = createEventHandler(true)
window.addEventListener('click',eventHandler)
// ...
window.removeEventListener('click',eventHandler)
,
call(e => foo(e))
与以下内容完全相同:
call(foo)
只有一层不必要的间接调用;)
这与函数式编程或currying无关,我看不到它如何阻碍您的调试经验。
当您想锁定某些参数或签名不兼容时,通常会包装。例如,
call(a => foo(5,a))
但是在这种情况下,您可能需要考虑使用curring。