使用撰写有什么好处
What is the benefit of using compose?
我正在学习使用Ramda并遇到作曲。但我无法理解它的目的
let value = R.compose( calledThird, calledSecond, calledFirst('hello') );
// vs
let value = calledThird( calledSecond( calledFirst('hello') ) );
纯粹是为了允许咖喱吗?也许。。。
let curried = R.compose( calledThird, calledSecond, calledFirst );
curried('hello');
还有其他目的吗?
你的第二个例子正是它的原因,尽管这实际上与咖喱无关。
函数组合允许您从更简单的函数中构建更复杂的函数。
假设您有一些需要排序的数据类型,假设是约会的集合。 假设您已经有一个 sortByDate
函数和一个 reverse
函数,您可以将sortByDateDescending
编写为
var sortByDateDescending = function(appointments) {
return reverse(sortByDate(appointments));
}
或在 ES6 中:
const sortByDateDescending = appointments => reverse(sortByDate(appointments));
这没有错。 但是,如果您要使用 compose
助手编写它,它有几个优点:
var sortByDateDescending = compose(reverse, sortByDate);
首先,它显然更短,并且随着您添加更多功能,差异会越来越大,尤其是对于 pre-es6 代码。
但更重要的是,这可以让您专注于有意义的事情。 您在这里组合功能;最终将传递的数据是目标,但是当您构建新功能时,这主要是
分散注意力。通过这样写,你可以专注于正在发生的事情:你按日期对列表进行排序,然后你正在反转结果。
更紧密地关注函数式编程的语言使这变得更加简单,使用不显眼的运算符而不是像compose
这样的函数。 在 Haskell 中,等效物看起来像
sortByDateDescending = reverse . sortByDate
但是Javascript并没有提供这种优雅。 我们能做的最好的事情就是创建像compose
这样的函数(或其顺序颠倒的孪生体,pipe
)。
我对Ramda帖子的介绍提供了更多以这种风格工作的例子。
顺便说一下,咖喱完全是一种不同的野兽。 这是一种技术,可以更轻松地在此类组合中重用函数。 但这主要是分散注意力。 如果你有兴趣,我也有一篇关于这个问题的帖子。
斯科特的回答很棒 - 只是想添加一些更多现实生活中的例子。
当您看到大量此类模式时,您可以确定需要改进代码的地方,在这些模式中,您不断使用直通函数处理一些数据:
var list = [3, 4, 1, 2];
list = filterOutEvens(list);
list = sort(list);
list = prependFoo(list);
你可能会想做这样的事情:
[3, 4, 1, 2].filterOutEvens().sort().prependFoo();
但是你记得,要做到这一点,你必须向Array.prototype添加东西,这绝对是不行的。
R.compose 为您提供了下一个最好的东西(请记住,它从右到左工作):
var processList = R.compose(prependFoo, sort, filterOutEvens);
processList([3, 4, 1, 2]);
如果你想使用它,这里是完整的例子:
function filterOutEvens(list) {
return list.filter(function(item) {
return item % 2 !== 0;
});
}
function sort(list) {
// More cleanly use R.sort here instead of native Array.prototype.sort, which operates in-place.
var diff = function(a, b) { return a - b; };
return R.sort(diff, list);
}
function prependFoo(list) {
return list.map(function(item) {
return 'foo-' + item;
});
}
var processList = R.compose(prependFoo, sort, filterOutEvens);
var result = processList([3, 4, 1, 2]);
// -> ["foo-1", "foo-3"]
// Display Stackoverflow snippet output.
document.body.innerHTML = JSON.stringify(result, null, 2);
<script src="//cdn.jsdelivr.net/ramda/0.19.1/ramda.min.js"></script>
- 这是什么 ==- javascript 运算符
- 我的单元测试选项是什么
- 全局变量和全局对象的属性之间有什么区别吗
- 打破承诺链的好方法是什么
- 在AngularJS应用程序中使用封装指令和路由的推荐方式是什么
- Javascript中的空白是什么
- 是什么让一个“;Uncaught RangeError:超过了最大调用堆栈大小“;错误(Chrome,在其他浏览器中显示
- 在ember/handlers中使用value和valueBinding有什么区别
- 什么'在webpack外部设置中,reactDom和reactDom不同
- 在JavaScript中拆分日期字符串的更好方法是什么
- 为什么$.brower被弃用?还有什么更好的替代方案
- 什么是&&在没有if的行中的变量之间
- 将jQuery.ech()方法转换为本地JavaScript抽象的最佳方法是什么
- 处理浮点错误的最佳方法是什么
- DOM元素和angular元素之间的主要区别是什么
- javascript导入的最佳实践是什么
- 这两个关于 JavaScript 作用域链的例子有什么区别?
- 什么's本地node.js服务器和python简单http服务器之间的区别
- 基于窗口宽度jquery的函数的替代方法是什么
- 什么'是在asp.net MVC中将本地化的resources.resx文件转换为javascript文件的有效